mirror of
https://bitbucket.org/projectswg/lightspeed.git
synced 2026-09-28 14:12:57 -04:00
Massive refactoring and fixed the client
This commit is contained in:
@@ -24,5 +24,6 @@
|
||||
<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="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<property name="lib" location="${opdir}/lib"/>
|
||||
<property name="dist" location="${bin}/dist"/>
|
||||
<property name="jar" location="${dist}/ProjectSWG.jar"/>
|
||||
<property name="ext-jar" location="${dist}/ProjectSWG-dependencies.jar"/>
|
||||
|
||||
<path id="ant.path">
|
||||
<fileset dir="lib/ant/">
|
||||
@@ -26,9 +27,7 @@
|
||||
<target name="compile" depends="init" description="Compile the sources">
|
||||
<path id="classpath">
|
||||
<pathelement path="${classpath}"/>
|
||||
<fileset dir="${lib}">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${lib}" includes="**/*.jar" />
|
||||
</path>
|
||||
<!-- Compile sources -->
|
||||
<javac srcdir="${src}" destdir="${bin}" includeantruntime="true" fork="true" debug="true">
|
||||
@@ -46,9 +45,7 @@
|
||||
<pathelement location="${bin}" />
|
||||
<pathelement location="hamcrest-core-1.3.jar" />
|
||||
<pathelement location="junit-4.12.jar" />
|
||||
<fileset dir="${lib}">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${lib}" includes="**/*.jar" />
|
||||
</classpath>
|
||||
<test name="main.TestAll" haltonfailure="no">
|
||||
</test>
|
||||
@@ -61,22 +58,26 @@
|
||||
<mkdir dir="${dist}"/>
|
||||
<!-- Create the classpath -->
|
||||
<path id="classpath">
|
||||
<pathelement location="${bin}" />
|
||||
<fileset dir="${lib}">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
<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 -->
|
||||
<manifestclasspath property="manifest.classpath" jarfile="${jar}">
|
||||
<classpath refid="classpath" />
|
||||
</manifestclasspath>
|
||||
<jar jarfile="${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.ProjectSWG"/>
|
||||
<attribute name="Class-Path" value="${manifest.classpath}"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
<delete file="${ext-jar}" />
|
||||
</target>
|
||||
|
||||
<target name="clean" description="Clean up">
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.ScrollPane?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<fx:root type="com.projectswg.lightspeed_frontend.gui.primary_tabs.DeploymentTab" xmlns:fx="http://javafx.com/fxml" stylesheets="@Deployment.css">
|
||||
<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="ALWAYS" minWidth="150.0" percentWidth="80" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="NEVER" prefHeight="50" />
|
||||
<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 vgrow="NEVER" prefHeight="40" />
|
||||
<RowConstraints vgrow="NEVER" prefHeight="40" />
|
||||
<RowConstraints vgrow="ALWAYS" prefHeight="75" />
|
||||
</rowConstraints>
|
||||
<ComboBox fx:id="deploymentComboBox" GridPane.fillWidth="true" maxWidth="200" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
||||
<Label text="Server:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="1" />
|
||||
<Label text="Build #:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="2" />
|
||||
<Label text="Deployment #:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="3" />
|
||||
<Label text="Status:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="4" />
|
||||
<Label text="Start Time:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="5" />
|
||||
<Label text="Uptime:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="6" />
|
||||
<Label text="Deployment Log:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="7" />
|
||||
|
||||
<Label fx:id="serverNameText" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<Label fx:id="buildIdText" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||
<Label fx:id="deploymentIdText" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<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" />
|
||||
|
||||
<VBox styleClass="log-wrapper" GridPane.columnIndex="0" GridPane.rowIndex="8" GridPane.columnSpan="2">
|
||||
<padding>
|
||||
<Insets top="5.0" left="5.0" right="5.0" bottom="5.0" />
|
||||
</padding>
|
||||
<Label fx:id="logText" styleClass="log" GridPane.hgrow="ALWAYS" />
|
||||
</VBox>
|
||||
</fx:root>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 507.2 507.2" style="enable-background:new 0 0 507.2 507.2;" xml:space="preserve">
|
||||
<circle style="fill:#32BA7C;" cx="253.6" cy="253.6" r="253.6"/>
|
||||
<path style="fill:#0AA06E;" d="M188.8,368l130.4,130.4c108-28.8,188-127.2,188-244.8c0-2.4,0-4.8,0-7.2L404.8,152L188.8,368z"/>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M260,310.4c11.2,11.2,11.2,30.4,0,41.6l-23.2,23.2c-11.2,11.2-30.4,11.2-41.6,0L93.6,272.8
|
||||
c-11.2-11.2-11.2-30.4,0-41.6l23.2-23.2c11.2-11.2,30.4-11.2,41.6,0L260,310.4z"/>
|
||||
<path style="fill:#FFFFFF;" d="M348.8,133.6c11.2-11.2,30.4-11.2,41.6,0l23.2,23.2c11.2,11.2,11.2,30.4,0,41.6l-176,175.2
|
||||
c-11.2,11.2-30.4,11.2-41.6,0l-23.2-23.2c-11.2-11.2-11.2-30.4,0-41.6L348.8,133.6z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 507.2 507.2" style="enable-background:new 0 0 507.2 507.2;" xml:space="preserve">
|
||||
<circle style="fill:#F15249;" cx="253.6" cy="253.6" r="253.6"/>
|
||||
<path style="fill:#AD0E0E;" d="M147.2,368L284,504.8c115.2-13.6,206.4-104,220.8-219.2L367.2,148L147.2,368z"/>
|
||||
<path style="fill:#FFFFFF;" d="M373.6,309.6c11.2,11.2,11.2,30.4,0,41.6l-22.4,22.4c-11.2,11.2-30.4,11.2-41.6,0l-176-176
|
||||
c-11.2-11.2-11.2-30.4,0-41.6l23.2-23.2c11.2-11.2,30.4-11.2,41.6,0L373.6,309.6z"/>
|
||||
<path style="fill:#D6D6D6;" d="M280.8,216L216,280.8l93.6,92.8c11.2,11.2,30.4,11.2,41.6,0l23.2-23.2c11.2-11.2,11.2-30.4,0-41.6
|
||||
L280.8,216z"/>
|
||||
<path style="fill:#FFFFFF;" d="M309.6,133.6c11.2-11.2,30.4-11.2,41.6,0l23.2,23.2c11.2,11.2,11.2,30.4,0,41.6L197.6,373.6
|
||||
c-11.2,11.2-30.4,11.2-41.6,0l-22.4-22.4c-11.2-11.2-11.2-30.4,0-41.6L309.6,133.6z"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,6 +1,8 @@
|
||||
#primaryViewContainer {
|
||||
-fx-background-color: #000000;
|
||||
-fx-text-fill: #FFFFFF;
|
||||
-fx-pref-width: 800;
|
||||
-fx-pref-height: 640;
|
||||
}
|
||||
|
||||
#commonPanel {
|
||||
@@ -1,39 +1,41 @@
|
||||
<?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.scene.layout.HBox?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.MenuButton?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import java.net.URL?>
|
||||
|
||||
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml/1" fx:id="primaryViewContainer" stylesheets="@PrimaryView.css" >
|
||||
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:id="primaryViewContainer" stylesheets="@PrimaryView.css" fx:controller="com.projectswg.lightspeed_frontend.gui.LightspeedPrimaryView">
|
||||
<HBox fx:id="commonPanel" alignment="CENTER_RIGHT" HBox.hgrow="ALWAYS" spacing="5.0">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
<MenuButton fx:id="commonServerStatus" mnemonicParsing="false" />
|
||||
<MenuButton fx:id="commonBuildStatus" mnemonicParsing="false" />
|
||||
<MenuButton fx:id="commonDeploymentStatus" mnemonicParsing="false" />
|
||||
</HBox>
|
||||
<TabPane tabClosingPolicy="UNAVAILABLE">
|
||||
<TabPane tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
|
||||
<tabs>
|
||||
<Tab text="General">
|
||||
<content>
|
||||
<com.projectswg.lightspeed_frontend.gui.primary_tabs.GeneralTab fx:id="generalTab" />
|
||||
<fx:include source="primary_tabs/General.fxml" />
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab text="Build">
|
||||
<content>
|
||||
<com.projectswg.lightspeed_frontend.gui.primary_tabs.BuildTab fx:id="buildTab" />
|
||||
<fx:include source="primary_tabs/Build.fxml" />
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab text="Deployment">
|
||||
<content>
|
||||
<com.projectswg.lightspeed_frontend.gui.primary_tabs.DeploymentTab fx:id="deploymentTab" />
|
||||
<fx:include source="primary_tabs/Deployment.fxml" />
|
||||
</content>
|
||||
</Tab>
|
||||
</tabs>
|
||||
</TabPane>
|
||||
</fx:root>
|
||||
</VBox>
|
||||
@@ -1,13 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?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?>
|
||||
|
||||
<fx:root type="com.projectswg.lightspeed_frontend.gui.primary_tabs.BuildTab" xmlns:fx="http://javafx.com/fxml" stylesheets="@Build.css" >
|
||||
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:id="rootBuild" stylesheets="@Build.css" fx:controller="com.projectswg.lightspeed_frontend.gui.primary_tabs.BuildTab">
|
||||
<padding>
|
||||
<Insets top="5.0" left="5.0" right="5.0" bottom="5.0" />
|
||||
</padding>
|
||||
@@ -41,5 +45,4 @@
|
||||
<Label fx:id="compileTimeText" GridPane.columnIndex="1" GridPane.rowIndex="5" />
|
||||
<Label fx:id="modeText" GridPane.columnIndex="1" GridPane.rowIndex="6" />
|
||||
<Label fx:id="testText" GridPane.columnIndex="1" GridPane.rowIndex="7" />
|
||||
</fx:root>
|
||||
|
||||
</GridPane>
|
||||
@@ -10,15 +10,13 @@
|
||||
-fx-text-fill: #04ff00;
|
||||
}
|
||||
|
||||
.log-wrapper {
|
||||
.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;
|
||||
}
|
||||
|
||||
.log {
|
||||
-fx-text-fill: #FFFFFF;
|
||||
-fx-alignment: top-left;
|
||||
-fx-text-alignment: left;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?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?>
|
||||
|
||||
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:id="rootDeployment" stylesheets="@Deployment.css" fx:controller="com.projectswg.lightspeed_frontend.gui.primary_tabs.DeploymentTab">
|
||||
<padding>
|
||||
<Insets top="5.0" left="5.0" right="5.0" bottom="5.0" />
|
||||
</padding>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="200.0" minWidth="100.0" />
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="150.0" percentWidth="80" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="NEVER" prefHeight="50" />
|
||||
<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 vgrow="NEVER" prefHeight="40" />
|
||||
<RowConstraints vgrow="NEVER" prefHeight="40" />
|
||||
</rowConstraints>
|
||||
<ComboBox fx:id="deploymentComboBox" GridPane.fillWidth="true" maxWidth="200" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
||||
<Label text="Server:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="1" />
|
||||
<Label text="Build #:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="2" />
|
||||
<Label text="Deployment #:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="3" />
|
||||
<Label text="Status:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="4" />
|
||||
<Label text="Start Time:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="5" />
|
||||
<Label text="Uptime:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="6" />
|
||||
<Label text="Deployment Log:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="7" />
|
||||
|
||||
<Label fx:id="serverNameText" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<Label fx:id="buildIdText" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||
<Label fx:id="deploymentIdText" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<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" />
|
||||
</GridPane>
|
||||
<TextArea fx:id="logTextArea" styleClass="log" editable="false" maxHeight="Infinity" VBox.vgrow="ALWAYS" />
|
||||
</VBox>
|
||||
@@ -1,14 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.ChoiceBox?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?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?>
|
||||
|
||||
<fx:root type="com.projectswg.lightspeed_frontend.gui.primary_tabs.GeneralTab" xmlns:fx="http://javafx.com/fxml" stylesheets="@General.css" >
|
||||
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:id="rootGeneral" stylesheets="@General.css" fx:controller="com.projectswg.lightspeed_frontend.gui.primary_tabs.GeneralTab">
|
||||
<padding>
|
||||
<Insets top="5.0" left="5.0" right="5.0" bottom="5.0" />
|
||||
</padding>
|
||||
@@ -36,4 +39,4 @@
|
||||
<Label fx:id="deploymentStatusText" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Label fx:id="populationText" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
||||
<Label fx:id="uptimeText" GridPane.columnIndex="1" GridPane.rowIndex="5" />
|
||||
</fx:root>
|
||||
</GridPane>
|
||||
@@ -1,70 +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;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.lightspeed.server.ServerServerData;
|
||||
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
|
||||
|
||||
public class CombinedLightspeed {
|
||||
|
||||
public static void main(String [] args) {
|
||||
ServerServerData server = getServer();
|
||||
if (server == null)
|
||||
return;
|
||||
AtomicBoolean running = new AtomicBoolean(true);
|
||||
int port = LightweightLightspeed.runConcurrent(server, running);
|
||||
LightspeedFrontendGUI.main(new String[]{"--address=localhost", "--port=" + port});
|
||||
running.set(false);
|
||||
}
|
||||
|
||||
private static ServerServerData getServer() {
|
||||
try {
|
||||
if (System.getProperty("os.name").toLowerCase().contains("win"))
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
JFileChooser chooser = new JFileChooser(new File("/home/josh/devel/ProjectSWG/swg_workspace/Holocore"));
|
||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
chooser.setAcceptAllFileFilterUsed(false);
|
||||
if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION)
|
||||
return null;
|
||||
ServerServerData server = new ServerServerData("LIGHTSPEED");
|
||||
server.setDirectory(chooser.getSelectedFile().getAbsolutePath());
|
||||
return server;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,9 +30,11 @@ package com.projectswg;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
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.info.HeavyweightDataManager;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.lightspeed.LightspeedManager;
|
||||
import com.projectswg.lightspeed.LightspeedMainManager;
|
||||
|
||||
public class Lightspeed {
|
||||
|
||||
@@ -42,13 +44,14 @@ public class Lightspeed {
|
||||
public static void main(String [] args) {
|
||||
if (MAIN_THREAD.get() != null)
|
||||
throw new IllegalStateException("Cannot run main() twice!");
|
||||
Log.addWrapper(new ConsoleLogWrapper(LogLevel.VERBOSE));
|
||||
MAIN_THREAD.set(Thread.currentThread());
|
||||
LightspeedManager.setDataManager(new HeavyweightDataManager());
|
||||
LightspeedManager.getDataManager().initialize();
|
||||
LightspeedManager lightspeed = new LightspeedManager();
|
||||
LightspeedMainManager.setDataManager(new HeavyweightDataManager());
|
||||
LightspeedMainManager.getDataManager().initialize();
|
||||
LightspeedMainManager lightspeed = new LightspeedMainManager();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(Lightspeed::doShutdown, "lightspeed-shutdown-hook"));
|
||||
runLightspeed(lightspeed);
|
||||
LightspeedManager.getDataManager().terminate();
|
||||
LightspeedMainManager.getDataManager().terminate();
|
||||
}
|
||||
|
||||
public static void requestShutdown() {
|
||||
@@ -66,7 +69,7 @@ public class Lightspeed {
|
||||
}
|
||||
}
|
||||
|
||||
private static void runLightspeed(LightspeedManager lightspeed) {
|
||||
private static void runLightspeed(LightspeedMainManager lightspeed) {
|
||||
Log.i("Initializing...");
|
||||
lightspeed.initialize();
|
||||
Log.i("Initialized.");
|
||||
|
||||
@@ -29,18 +29,18 @@ package com.projectswg;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
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.common.info.Log;
|
||||
import com.projectswg.lightspeed.LightspeedManager;
|
||||
import com.projectswg.lightspeed.LightspeedMainManager;
|
||||
import com.projectswg.lightspeed.server.ServerServerData;
|
||||
|
||||
public class LightweightLightspeed {
|
||||
|
||||
public static int runConcurrent(ServerServerData server, AtomicBoolean running) {
|
||||
Thread mainThread = Thread.currentThread();
|
||||
LightspeedManager.setDataManager(createDataManager(0, server));
|
||||
LightspeedMainManager.setDataManager(createDataManager(0, server));
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
running.set(false);
|
||||
mainThread.interrupt();
|
||||
@@ -49,7 +49,7 @@ public class LightweightLightspeed {
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
}
|
||||
LightspeedManager.getDataManager().terminate();
|
||||
LightspeedMainManager.getDataManager().terminate();
|
||||
}, "lightspeed-shutdown-hook"));
|
||||
return runLightspeedConcurrent(running);
|
||||
}
|
||||
@@ -57,13 +57,13 @@ public class LightweightLightspeed {
|
||||
public static void run(int port, ServerServerData server) {
|
||||
Thread mainThread = Thread.currentThread();
|
||||
AtomicBoolean running = new AtomicBoolean(true);
|
||||
LightspeedManager.setDataManager(createDataManager(port, server));
|
||||
LightspeedMainManager.setDataManager(createDataManager(port, server));
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
running.set(false);
|
||||
mainThread.interrupt();
|
||||
}, "lightspeed-shutdown-hook"));
|
||||
runLightspeed(running);
|
||||
LightspeedManager.getDataManager().terminate();
|
||||
LightspeedMainManager.getDataManager().terminate();
|
||||
}
|
||||
|
||||
private static LightweightDataManager createDataManager(int port, ServerServerData server) {
|
||||
@@ -76,7 +76,7 @@ public class LightweightLightspeed {
|
||||
}
|
||||
|
||||
private static void runLightspeed(AtomicBoolean running) {
|
||||
LightspeedManager lightspeed = new LightspeedManager();
|
||||
LightspeedMainManager lightspeed = new LightspeedMainManager();
|
||||
Log.i("Lightspeed", "Initializing...");
|
||||
lightspeed.initialize();
|
||||
Log.i("Lightspeed", "Initialized.");
|
||||
@@ -99,7 +99,7 @@ public class LightweightLightspeed {
|
||||
}
|
||||
|
||||
private static int runLightspeedConcurrent(AtomicBoolean running) {
|
||||
LightspeedManager lightspeed = new LightspeedManager();
|
||||
LightspeedMainManager lightspeed = new LightspeedMainManager();
|
||||
Log.i("Lightspeed", "Initializing...");
|
||||
lightspeed.initialize();
|
||||
Log.i("Lightspeed", "Initialized.");
|
||||
|
||||
@@ -1,106 +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.common.callback;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.utilities.ThreadUtilities;
|
||||
|
||||
class BaseCallbackManager {
|
||||
|
||||
private final Object executorMutex;
|
||||
private final String name;
|
||||
private final int threadCount;
|
||||
private final AtomicBoolean shutdown;
|
||||
private ExecutorService executor;
|
||||
|
||||
public BaseCallbackManager(String name) {
|
||||
this(name, 1);
|
||||
}
|
||||
|
||||
public BaseCallbackManager(String name, int threadCount) {
|
||||
this.executorMutex = new Object();
|
||||
this.name = name;
|
||||
this.threadCount = threadCount;
|
||||
this.shutdown = new AtomicBoolean(false);
|
||||
this.executor = null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
synchronized (executorMutex) {
|
||||
if (executor != null && !shutdown.get())
|
||||
executor.shutdown();
|
||||
shutdown.set(false);
|
||||
if (threadCount <= 1)
|
||||
executor = Executors.newSingleThreadExecutor(ThreadUtilities.newThreadFactory(name+"-callback-manager"));
|
||||
else
|
||||
executor = Executors.newFixedThreadPool(threadCount, ThreadUtilities.newThreadFactory(name+"-callback-manager-%d"));
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized (executorMutex) {
|
||||
executor.shutdown();
|
||||
shutdown.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) {
|
||||
synchronized (executorMutex) {
|
||||
if (executor == null)
|
||||
return true;
|
||||
if (!shutdown.get())
|
||||
throw new IllegalStateException("Cannot wait for termination when never stopped!");
|
||||
try {
|
||||
return executor.awaitTermination(timeout, unit);
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean call(Runnable r) {
|
||||
synchronized (executorMutex) {
|
||||
if (executor == null)
|
||||
throw new IllegalStateException("Manager has not been started!");
|
||||
if (shutdown.get())
|
||||
return false;
|
||||
try {
|
||||
executor.execute(r);
|
||||
return true;
|
||||
} catch (RejectedExecutionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +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.common.callback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
public class CallbackManager<T> extends BaseCallbackManager {
|
||||
|
||||
private final List<T> callbacks;
|
||||
|
||||
public CallbackManager(String name) {
|
||||
this(name, 1);
|
||||
}
|
||||
|
||||
public CallbackManager(String name, int threadCount) {
|
||||
super(name, threadCount);
|
||||
this.callbacks = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addCallback(T callback) {
|
||||
synchronized (callbacks) {
|
||||
callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeCallback(T callback) {
|
||||
synchronized (callbacks) {
|
||||
callbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCallback(T callback) {
|
||||
synchronized (callbacks) {
|
||||
callbacks.clear();
|
||||
callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCallbacks() {
|
||||
synchronized (callbacks) {
|
||||
callbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean callOnEach(CallCallback<T> call) {
|
||||
synchronized (callbacks) {
|
||||
return call(() -> {
|
||||
for (T callback : callbacks) {
|
||||
try {
|
||||
call.run(callback);
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface CallCallback<T> {
|
||||
void run(T callback);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +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.common.concurrency;
|
||||
|
||||
public class PswgBasicScheduledThread extends PswgScheduledThreadPool {
|
||||
|
||||
private final Runnable runnable;
|
||||
|
||||
public PswgBasicScheduledThread(String name, Runnable runnable) {
|
||||
super(1, name);
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
throw new UnsupportedOperationException("Cannot use this function. Must use startX(initialDelay, periodicDelay)");
|
||||
}
|
||||
|
||||
public void startWithFixedRate(long initialDelay, long periodicDelay) {
|
||||
super.start();
|
||||
super.executeWithFixedRate(initialDelay, periodicDelay, runnable);
|
||||
}
|
||||
|
||||
public void startWithFixedDelay(long initialDelay, long periodicDelay) {
|
||||
super.start();
|
||||
super.executeWithFixedDelay(initialDelay, periodicDelay, runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeWithFixedRate(long initialDelay, long periodicDelay, Runnable runnable) {
|
||||
throw new UnsupportedOperationException("Runnable is defined in the constructor!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeWithFixedDelay(long initialDelay, long periodicDelay, Runnable runnable) {
|
||||
throw new UnsupportedOperationException("Runnable is defined in the constructor!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +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.common.concurrency;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class PswgBasicThread extends PswgThreadPool {
|
||||
|
||||
private final AtomicBoolean executing;
|
||||
private final Runnable runnable;
|
||||
|
||||
public PswgBasicThread(String name, Runnable runnable) {
|
||||
super(1, name);
|
||||
this.executing = new AtomicBoolean(false);
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
super.execute(() -> {
|
||||
executing.set(true);
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
executing.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isExecuting() {
|
||||
return executing.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
throw new UnsupportedOperationException("Runnable is defined in the constructor!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,115 +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.common.concurrency;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
|
||||
public class PswgScheduledThreadPool {
|
||||
|
||||
private final AtomicBoolean running;
|
||||
private final int nThreads;
|
||||
private final ThreadFactory threadFactory;
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
public PswgScheduledThreadPool(int nThreads, String nameFormat) {
|
||||
this.running = new AtomicBoolean(false);
|
||||
this.nThreads = nThreads;
|
||||
this.threadFactory = new CustomThreadFactory(nameFormat);
|
||||
this.executor = null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Assert.test(!running.getAndSet(true));
|
||||
executor = Executors.newScheduledThreadPool(nThreads, threadFactory);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Assert.test(running.getAndSet(false));
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
public void executeWithFixedRate(long initialDelay, long time, Runnable runnable) {
|
||||
Assert.test(running.get());
|
||||
executor.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}, initialDelay, time, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void executeWithFixedDelay(long initialDelay, long time, Runnable runnable) {
|
||||
Assert.test(running.get());
|
||||
executor.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}, initialDelay, time, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public boolean awaitTermination(long time) {
|
||||
Assert.notNull(executor);
|
||||
try {
|
||||
return executor.awaitTermination(time, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomThreadFactory implements ThreadFactory {
|
||||
|
||||
private final String pattern;
|
||||
private int counter;
|
||||
|
||||
public CustomThreadFactory(String pattern) {
|
||||
this.pattern = pattern;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
String name;
|
||||
if (pattern.contains("%d"))
|
||||
name = String.format(pattern, counter++);
|
||||
else
|
||||
name = pattern;
|
||||
return new Thread(r, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +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.common.concurrency;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
|
||||
public class PswgThreadPool {
|
||||
|
||||
private final AtomicBoolean running;
|
||||
private final int nThreads;
|
||||
private final ThreadFactory threadFactory;
|
||||
private ExecutorService executor;
|
||||
|
||||
public PswgThreadPool(int nThreads, String nameFormat) {
|
||||
this.running = new AtomicBoolean(false);
|
||||
this.nThreads = nThreads;
|
||||
this.threadFactory = new CustomThreadFactory(nameFormat);
|
||||
this.executor = null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Assert.test(!running.getAndSet(true));
|
||||
executor = Executors.newFixedThreadPool(nThreads, threadFactory);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Assert.test(running.getAndSet(false));
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
public void execute(Runnable runnable) {
|
||||
Assert.test(running.get());
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean awaitTermination(long time) {
|
||||
Assert.notNull(executor);
|
||||
try {
|
||||
return executor.awaitTermination(time, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running.get();
|
||||
}
|
||||
|
||||
private static class CustomThreadFactory implements ThreadFactory {
|
||||
|
||||
private final String pattern;
|
||||
private int counter;
|
||||
|
||||
public CustomThreadFactory(String pattern) {
|
||||
this.pattern = pattern;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
String name;
|
||||
if (pattern.contains("%d"))
|
||||
name = String.format(pattern, counter++);
|
||||
else
|
||||
name = pattern;
|
||||
return new Thread(r, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +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.common.concurrency;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class SmartLock {
|
||||
|
||||
private final Lock lock;
|
||||
private final Condition condition;
|
||||
|
||||
public SmartLock() {
|
||||
this.lock = new ReentrantLock(true);
|
||||
this.condition = lock.newCondition();
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
lock.lockInterruptibly();
|
||||
}
|
||||
|
||||
public boolean tryLock() {
|
||||
return lock.tryLock();
|
||||
}
|
||||
|
||||
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
|
||||
return lock.tryLock(time, unit);
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public void await() throws InterruptedException {
|
||||
lock();
|
||||
try {
|
||||
condition.await();
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void awaitUninterruptibly() {
|
||||
lock();
|
||||
try {
|
||||
condition.awaitUninterruptibly();
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public long awaitNanos(long nanosTimeout) throws InterruptedException {
|
||||
lock();
|
||||
try {
|
||||
return condition.awaitNanos(nanosTimeout);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean await(long time, TimeUnit unit) throws InterruptedException {
|
||||
lock();
|
||||
try {
|
||||
return condition.await(time, unit);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean awaitUntil(Date deadline) throws InterruptedException {
|
||||
lock();
|
||||
try {
|
||||
return condition.awaitUntil(deadline);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void signal() {
|
||||
lock();
|
||||
try {
|
||||
condition.signal();
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void signalAll() {
|
||||
lock();
|
||||
try {
|
||||
condition.signalAll();
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,151 +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.common.concurrency;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Queue;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SynchronizedQueue<T> implements Queue<T> {
|
||||
|
||||
private final Queue<T> queue;
|
||||
|
||||
public SynchronizedQueue() {
|
||||
this(new ArrayDeque<>());
|
||||
}
|
||||
|
||||
public SynchronizedQueue(Queue<T> queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public synchronized void forEach(Consumer<? super T> action) {
|
||||
queue.forEach(action);
|
||||
}
|
||||
|
||||
public synchronized boolean add(T e) {
|
||||
return queue.add(e);
|
||||
}
|
||||
|
||||
public synchronized boolean offer(T e) {
|
||||
return queue.offer(e);
|
||||
}
|
||||
|
||||
public synchronized int size() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
public synchronized boolean isEmpty() {
|
||||
return queue.isEmpty();
|
||||
}
|
||||
|
||||
public synchronized boolean contains(Object o) {
|
||||
return queue.contains(o);
|
||||
}
|
||||
|
||||
public synchronized T remove() {
|
||||
return queue.remove();
|
||||
}
|
||||
|
||||
public synchronized T poll() {
|
||||
return queue.poll();
|
||||
}
|
||||
|
||||
public synchronized T element() {
|
||||
return queue.element();
|
||||
}
|
||||
|
||||
public synchronized Iterator<T> iterator() {
|
||||
return queue.iterator();
|
||||
}
|
||||
|
||||
public synchronized T peek() {
|
||||
return queue.peek();
|
||||
}
|
||||
|
||||
public synchronized Object[] toArray() {
|
||||
return queue.toArray();
|
||||
}
|
||||
|
||||
public synchronized <E> E[] toArray(E[] a) {
|
||||
return queue.toArray(a);
|
||||
}
|
||||
|
||||
public synchronized boolean remove(Object o) {
|
||||
return queue.remove(o);
|
||||
}
|
||||
|
||||
public synchronized boolean containsAll(Collection<?> c) {
|
||||
return queue.containsAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean addAll(Collection<? extends T> c) {
|
||||
return queue.addAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean removeAll(Collection<?> c) {
|
||||
return queue.removeAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean removeIf(Predicate<? super T> filter) {
|
||||
return queue.removeIf(filter);
|
||||
}
|
||||
|
||||
public synchronized boolean retainAll(Collection<?> c) {
|
||||
return queue.retainAll(c);
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
public synchronized boolean equals(Object o) {
|
||||
return queue.equals(o);
|
||||
}
|
||||
|
||||
public synchronized int hashCode() {
|
||||
return queue.hashCode();
|
||||
}
|
||||
|
||||
public synchronized Spliterator<T> spliterator() {
|
||||
return queue.spliterator();
|
||||
}
|
||||
|
||||
public synchronized Stream<T> stream() {
|
||||
return queue.stream();
|
||||
}
|
||||
|
||||
public synchronized Stream<T> parallelStream() {
|
||||
return queue.parallelStream();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,117 +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.common.control;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
public class Assert {
|
||||
|
||||
private static volatile AssertLevel level = AssertLevel.ASSERT;
|
||||
|
||||
public static void setLevel(AssertLevel level) {
|
||||
Assert.level = level;
|
||||
}
|
||||
|
||||
public static boolean debug() {
|
||||
return level != AssertLevel.IGNORE;
|
||||
}
|
||||
|
||||
public static void notNull(Object o) {
|
||||
notNull(o, "");
|
||||
}
|
||||
|
||||
public static void notNull(Object o, String message) {
|
||||
if (debug() && o == null)
|
||||
handle(new NullPointerException(message));
|
||||
}
|
||||
|
||||
public static void isNull(Object o) {
|
||||
isNull(o, "");
|
||||
}
|
||||
|
||||
public static void isNull(Object o, String message) {
|
||||
if (debug() && o != null)
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
public static void test(boolean expr) {
|
||||
test(expr, "");
|
||||
}
|
||||
|
||||
public static void test(boolean expr, String message) {
|
||||
if (debug() && !expr)
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
public static void fail() {
|
||||
fail("");
|
||||
}
|
||||
|
||||
public static void fail(String message) {
|
||||
if (debug())
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
private static void handle(RuntimeException e) {
|
||||
AssertLevel level = Assert.level;
|
||||
switch (level) {
|
||||
case WARN:
|
||||
warn(e);
|
||||
break;
|
||||
case ASSERT:
|
||||
throw e;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void warn(Exception e) {
|
||||
StackTraceElement [] elements = e.getStackTrace();
|
||||
if (elements.length <= 1)
|
||||
Log.e(e);
|
||||
else
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
private static class AssertionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AssertionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum AssertLevel {
|
||||
IGNORE,
|
||||
WARN,
|
||||
ASSERT
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,140 +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.common.control;
|
||||
|
||||
public abstract class Intent {
|
||||
|
||||
private boolean broadcasted;
|
||||
private boolean complete;
|
||||
private Intent parallel;
|
||||
private Intent sequential;
|
||||
|
||||
protected Intent() {
|
||||
this.broadcasted = false;
|
||||
this.complete = false;
|
||||
this.parallel = null;
|
||||
this.sequential = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the intent has been completed
|
||||
*/
|
||||
public synchronized void markAsComplete() {
|
||||
this.complete = true;
|
||||
if (sequential != null)
|
||||
sequential.broadcast();
|
||||
sequential = null;
|
||||
parallel = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the intent has been broadcasted and processed
|
||||
* by the system
|
||||
* @return TRUE if the intent has been broadcasted and processed, FALSE
|
||||
* otherwise
|
||||
*/
|
||||
public synchronized boolean isComplete() {
|
||||
return complete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the intent has been broadcasted to the system
|
||||
* @return TRUE if the intent has been broadcasted, FALSE otherwise
|
||||
*/
|
||||
public synchronized boolean isBroadcasted() {
|
||||
return broadcasted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the intent as the parameter to finish before this intent
|
||||
* starts
|
||||
* @param i the intent to execute after
|
||||
*/
|
||||
public synchronized void broadcastAfterIntent(Intent i) {
|
||||
if (i == null) {
|
||||
broadcast();
|
||||
return;
|
||||
}
|
||||
synchronized (i) {
|
||||
if (i.isComplete())
|
||||
broadcast();
|
||||
else
|
||||
i.setAsSequential(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the intent as the parameter to start before this intent starts
|
||||
* @param i the intent to execute with
|
||||
*/
|
||||
public synchronized void broadcastWithIntent(Intent i) {
|
||||
if (i == null) {
|
||||
broadcast();
|
||||
return;
|
||||
}
|
||||
synchronized (i) {
|
||||
if (!isComplete()) {
|
||||
setAsParallel(i);
|
||||
}
|
||||
broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts this node to the system
|
||||
*/
|
||||
public synchronized void broadcast() {
|
||||
if (broadcasted)
|
||||
throw new IllegalStateException("Intent has already been broadcasted!");
|
||||
broadcasted = true;
|
||||
IntentManager.getInstance().broadcastIntent(this);
|
||||
if (parallel != null)
|
||||
parallel.broadcast();
|
||||
parallel = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
private synchronized void setAsParallel(Intent i) {
|
||||
if (parallel == null)
|
||||
parallel = i;
|
||||
else
|
||||
parallel.setAsParallel(i);
|
||||
}
|
||||
|
||||
private synchronized void setAsSequential(Intent i) {
|
||||
if (sequential == null)
|
||||
sequential = i;
|
||||
else
|
||||
sequential.setAsParallel(i);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +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.common.control;
|
||||
|
||||
public class IntentChain {
|
||||
|
||||
private final Object mutex;
|
||||
private Intent i;
|
||||
|
||||
public IntentChain() {
|
||||
mutex = new Object();
|
||||
i = null;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
synchronized (mutex) {
|
||||
i = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastAfter(Intent i) {
|
||||
synchronized (mutex) {
|
||||
i.broadcastAfterIntent(this.i);
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,132 +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.common.control;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class IntentExecutor {
|
||||
|
||||
private final Queue<Runnable> tasks;
|
||||
private final AtomicBoolean shutdown;
|
||||
private final Signal taskSignal;
|
||||
|
||||
public IntentExecutor(int threadCount, String namePattern) {
|
||||
tasks = new ArrayDeque<>();
|
||||
shutdown = new AtomicBoolean(false);
|
||||
taskSignal = new Signal();
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
new IntentThread(String.format(namePattern, i));
|
||||
}
|
||||
}
|
||||
|
||||
public void execute(Runnable r) {
|
||||
synchronized (tasks) {
|
||||
tasks.add(r);
|
||||
}
|
||||
taskSignal.signal();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
synchronized (tasks) {
|
||||
return tasks.size();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
shutdown.set(true);
|
||||
taskSignal.signalAll();
|
||||
}
|
||||
|
||||
public void awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
// timeout = unit.toMillis(timeout);
|
||||
while (size() > 0 && timeout >= 0) {
|
||||
Thread.sleep(1);
|
||||
timeout--;
|
||||
}
|
||||
}
|
||||
|
||||
private class IntentThread implements Runnable {
|
||||
|
||||
private final Thread thread;
|
||||
|
||||
public IntentThread(String name) {
|
||||
thread = new Thread(this, name);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
Runnable r;
|
||||
synchronized (tasks) {
|
||||
r = tasks.poll();
|
||||
if (r == null) {
|
||||
if (shutdown.get())
|
||||
break;
|
||||
taskSignal.await();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Signal {
|
||||
|
||||
private final Object mutex = new Object();
|
||||
|
||||
public void signal() {
|
||||
synchronized (mutex) {
|
||||
mutex.notify();
|
||||
}
|
||||
}
|
||||
|
||||
public void signalAll() {
|
||||
synchronized (mutex) {
|
||||
mutex.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean await() {
|
||||
synchronized (mutex) {
|
||||
try {
|
||||
mutex.wait();
|
||||
return true;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,144 +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.common.control;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.utilities.ThreadUtilities;
|
||||
|
||||
|
||||
public class IntentManager {
|
||||
|
||||
private static final IntentManager INSTANCE = new IntentManager();
|
||||
|
||||
private final Runnable broadcastRunnable;
|
||||
private final Map <Class<? extends Intent>, List<IntentReceiver>> intentRegistrations;
|
||||
private final Queue <Intent> intentQueue;
|
||||
private ExecutorService broadcastThreads;
|
||||
private boolean initialized = false;
|
||||
private boolean terminated = false;
|
||||
|
||||
private IntentManager() {
|
||||
intentRegistrations = new HashMap<>();
|
||||
intentQueue = new IntentQueue<>();
|
||||
initialize();
|
||||
broadcastRunnable = () -> {
|
||||
Intent i;
|
||||
synchronized (intentQueue) {
|
||||
i = intentQueue.poll();
|
||||
}
|
||||
if (i != null)
|
||||
broadcast(i);
|
||||
};
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
if (!initialized) {
|
||||
final int broadcastThreadCount = Runtime.getRuntime().availableProcessors() * 10;
|
||||
broadcastThreads = Executors.newFixedThreadPool(broadcastThreadCount, ThreadUtilities.newThreadFactory("intent-processor-%d"));
|
||||
initialized = true;
|
||||
terminated = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
if (!terminated) {
|
||||
broadcastThreads.shutdown();
|
||||
initialized = false;
|
||||
terminated = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void broadcastIntent(Intent i) {
|
||||
if (i == null)
|
||||
throw new NullPointerException("Intent cannot be null!");
|
||||
synchronized (intentQueue) {
|
||||
intentQueue.add(i);
|
||||
}
|
||||
try { broadcastThreads.execute(broadcastRunnable); }
|
||||
catch (RejectedExecutionException e) { } // This error is thrown when the server is being shut down
|
||||
}
|
||||
|
||||
public void registerForIntent(Class<? extends Intent> c, IntentReceiver r) {
|
||||
if (r == null)
|
||||
throw new NullPointerException("Cannot register a null value for an intent");
|
||||
synchronized (intentRegistrations) {
|
||||
List <IntentReceiver> intents = intentRegistrations.get(c);
|
||||
if (intents == null) {
|
||||
intents = new CopyOnWriteArrayList<>();
|
||||
intentRegistrations.put(c, intents);
|
||||
}
|
||||
synchronized (intents) {
|
||||
intents.add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcast(Intent i) {
|
||||
List <IntentReceiver> receivers;
|
||||
synchronized (intentRegistrations) {
|
||||
receivers = intentRegistrations.get(i.getClass());
|
||||
}
|
||||
if (receivers == null) {
|
||||
i.markAsComplete();
|
||||
return;
|
||||
}
|
||||
for (IntentReceiver r : receivers) {
|
||||
broadcast(r, i);
|
||||
}
|
||||
i.markAsComplete();
|
||||
}
|
||||
|
||||
private void broadcast(IntentReceiver r, Intent i) {
|
||||
try {
|
||||
r.onIntentReceived(i);
|
||||
} catch (Throwable t) {
|
||||
Log.e("Fatal Exception while processing intent: " + i);
|
||||
Log.e(t);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIntentsQueued() {
|
||||
synchronized (getInstance().intentQueue) {
|
||||
return getInstance().intentQueue.size();
|
||||
}
|
||||
}
|
||||
|
||||
public static IntentManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,235 +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.common.control;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
|
||||
class IntentQueue<E> implements Queue<E> {
|
||||
|
||||
private final Node head;
|
||||
private int size;
|
||||
private int modificationCount;
|
||||
|
||||
public IntentQueue() {
|
||||
head = new Node(null, null, null); // Left = Forward, Right = Reverse
|
||||
head.left = head;
|
||||
head.right = head;
|
||||
modificationCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
Node n = head;
|
||||
while (n.left != head) {
|
||||
if (n.left.value == o)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
return new Iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object [] toArray() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T [] toArray(T [] a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
modificationCount++;
|
||||
Node n = head;
|
||||
while (n.left != head) {
|
||||
if (n.left.value == o) {
|
||||
n.left = n.left.left;
|
||||
n.left.right = n;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
for (Object o : c)
|
||||
if (!contains(o))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
boolean added = false;
|
||||
for (E i : c)
|
||||
added = add(i) || added;
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
boolean changed = false;
|
||||
for (Object o : c)
|
||||
changed = remove(o) || changed;
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
boolean changed = false;
|
||||
Node n = head;
|
||||
while (n.left != head) {
|
||||
if (!c.contains(n.left.value)) {
|
||||
n.left.left.right = n;
|
||||
n.left = n.left.left;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
modificationCount++;
|
||||
size = 0;
|
||||
head.left = head;
|
||||
head.right = head;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
head.right.left = new Node(e, head, head.right);
|
||||
head.right = head.right.left;
|
||||
modificationCount++;
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e) {
|
||||
return add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove() {
|
||||
if (isEmpty())
|
||||
throw new NoSuchElementException("Queue is empty!");
|
||||
modificationCount++;
|
||||
E i = head.left.value;
|
||||
head.left = head.left.left;
|
||||
head.left.right = head;
|
||||
size--;
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll() {
|
||||
if (isEmpty())
|
||||
return null;
|
||||
modificationCount++;
|
||||
E i = head.left.value;
|
||||
head.left = head.left.left;
|
||||
head.left.right = head;
|
||||
size--;
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E element() {
|
||||
if (isEmpty())
|
||||
throw new NoSuchElementException("Queue is empty!");
|
||||
return head.left.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peek() {
|
||||
if (isEmpty())
|
||||
return null;
|
||||
return head.left.value;
|
||||
}
|
||||
|
||||
private class Iterator implements java.util.Iterator<E> {
|
||||
|
||||
private final int modificationCount;
|
||||
private Node currentNode;
|
||||
|
||||
public Iterator() {
|
||||
this.modificationCount = IntentQueue.this.modificationCount;
|
||||
this.currentNode = IntentQueue.this.head;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (this.modificationCount != IntentQueue.this.modificationCount)
|
||||
throw new ConcurrentModificationException();
|
||||
return currentNode.left != IntentQueue.this.head;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (!hasNext())
|
||||
throw new NoSuchElementException("Iterator has reached the end of the queue!");
|
||||
E i = currentNode.left.value;
|
||||
currentNode = currentNode.left;
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class Node {
|
||||
|
||||
public final E value;
|
||||
public Node left;
|
||||
public Node right;
|
||||
|
||||
public Node(E value, Node left, Node right) {
|
||||
this.value = value;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+25
-6
@@ -27,15 +27,34 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.control;
|
||||
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.DataManager;
|
||||
|
||||
public interface IntentReceiver {
|
||||
public class LightspeedManager extends Manager {
|
||||
|
||||
/**
|
||||
* This function will be called if an intent is broadcasted and this
|
||||
* manager is listening for it, or if this manager is specifically given
|
||||
* this intent.
|
||||
* @param i the intent received
|
||||
* Gets the config object associated with a certain file, or NULL if the
|
||||
* file failed to load on startup
|
||||
* @param file the file to get the config for
|
||||
* @return the config object associated with the file, or NULL if the
|
||||
* config failed to load
|
||||
*/
|
||||
public void onIntentReceived(Intent i);
|
||||
public final Config getConfig(ConfigFile file) {
|
||||
return getDataManager().getConfig(file);
|
||||
}
|
||||
|
||||
public BackendData getBackendData() {
|
||||
return getDataManager().getBackendData();
|
||||
}
|
||||
|
||||
public static void setDataManager(DataManager dataManager) {
|
||||
LightspeedService.setDataManager(dataManager);
|
||||
}
|
||||
|
||||
public static DataManager getDataManager() {
|
||||
return LightspeedService.getDataManager();
|
||||
}
|
||||
|
||||
}
|
||||
+22
-27
@@ -25,43 +25,38 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.concurrency;
|
||||
package com.projectswg.common.control;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.DataManager;
|
||||
|
||||
public class PswgTaskThreadPool<T> extends PswgThreadPool {
|
||||
public class LightspeedService extends Service {
|
||||
|
||||
private final Queue<T> tasks;
|
||||
private final Runnable runner;
|
||||
private static DataManager dataManager = null;
|
||||
|
||||
public PswgTaskThreadPool(int nThreads, String namePattern, TaskExecutor<T> executor) {
|
||||
super(nThreads, namePattern);
|
||||
this.tasks = new ArrayDeque<>();
|
||||
this.runner = () -> {
|
||||
T t = null;
|
||||
synchronized (tasks) {
|
||||
t = tasks.poll();
|
||||
}
|
||||
if (t != null)
|
||||
executor.run(t);
|
||||
};
|
||||
/**
|
||||
* Gets the config object associated with a certain file, or NULL if the
|
||||
* file failed to load on startup
|
||||
* @param file the file to get the config for
|
||||
* @return the config object associated with the file, or NULL if the
|
||||
* config failed to load
|
||||
*/
|
||||
public final Config getConfig(ConfigFile file) {
|
||||
return getDataManager().getConfig(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
throw new UnsupportedOperationException("Runnable are posted automatically by addTask!");
|
||||
public BackendData getBackendData() {
|
||||
return getDataManager().getBackendData();
|
||||
}
|
||||
|
||||
public void addTask(T t) {
|
||||
synchronized (tasks) {
|
||||
tasks.add(t);
|
||||
}
|
||||
super.execute(runner);
|
||||
public static void setDataManager(DataManager dataManager) {
|
||||
LightspeedService.dataManager = dataManager;
|
||||
}
|
||||
|
||||
public interface TaskExecutor<T> {
|
||||
void run(T t);
|
||||
public static DataManager getDataManager() {
|
||||
return dataManager;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,187 +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.common.control;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
|
||||
/**
|
||||
* A Manager is a class that will manage services, and generally controls the
|
||||
* program as a whole
|
||||
*/
|
||||
public abstract class Manager extends Service {
|
||||
|
||||
private List <Service> children;
|
||||
|
||||
public Manager() {
|
||||
children = new ArrayList<Service>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this manager. If the manager returns false on this method
|
||||
* then the initialization failed and may not work as intended. This will
|
||||
* initialize all children automatically.
|
||||
* @return TRUE if initialization was successful, FALSE otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
boolean success = super.initialize();
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (!child.initialize()) {
|
||||
Log.e(child.getClass().getSimpleName() + " failed to initialize!");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this manager. If the manager returns false on this method then
|
||||
* the manger failed to start and may not work as intended. This will start
|
||||
* all children automatically.
|
||||
* @return TRUE if starting was successful, FALSE otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean start() {
|
||||
boolean success = super.start();
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (!child.start()) {
|
||||
Log.e(child.getClass().getSimpleName() + " failed to start!");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this manager. If the manager returns false on this method then
|
||||
* the manger failed to stop and may not have fully locked down. This will
|
||||
* start all children automatically.
|
||||
* @return TRUE if stopping was successful, FALSE otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean stop() {
|
||||
boolean success = super.stop(), cSuccess = true;
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (!success)
|
||||
break;
|
||||
cSuccess = child.stop();
|
||||
if (!cSuccess) {
|
||||
Log.e(child.getClass().getSimpleName() + " failed to stop!");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates this manager. If the manager returns false on this method
|
||||
* then the manager failed to shut down and resources may not have been
|
||||
* cleaned up. This will terminate all children automatically.
|
||||
* @return TRUE if termination was successful, FALSE otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean terminate() {
|
||||
boolean success = super.terminate();
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (!child.terminate())
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not this manager is operational
|
||||
* @return TRUE if this manager is operational, FALSE otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isOperational() {
|
||||
boolean success = true;
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (!child.isOperational())
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child to the manager's list of children. This creates a tree of
|
||||
* managers that allows information to propogate freely through the network
|
||||
* in an easy way.
|
||||
* @param m the manager to add as a child.
|
||||
*/
|
||||
public void addChildService(Service s) {
|
||||
if (s == null)
|
||||
throw new NullPointerException("Child service cannot be null!");
|
||||
synchronized (children) {
|
||||
for (Service child : children) {
|
||||
if (s == child || s.equals(child))
|
||||
return;
|
||||
}
|
||||
children.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the sub-manager from the list of children
|
||||
* @param m the sub-manager to remove
|
||||
*/
|
||||
public void removeChildService(Service s) {
|
||||
if (s == null)
|
||||
return;
|
||||
synchronized (children) {
|
||||
children.remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copied ArrayList of the children of this manager
|
||||
* @return a copied ArrayList of the children of this manager
|
||||
*/
|
||||
public List<Service> getManagerChildren() {
|
||||
synchronized (children) {
|
||||
return new ArrayList<Service>(children);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,122 +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.common.control;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.DataManager;
|
||||
|
||||
/**
|
||||
* A Service is a class that does a specific job for the application
|
||||
*/
|
||||
public abstract class Service {
|
||||
|
||||
private static DataManager dataManager = null;
|
||||
|
||||
public Service() {
|
||||
IntentManager.getInstance().initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this service. If the service returns false on this method
|
||||
* then the initialization failed and may not work as intended.
|
||||
* @return TRUE if initialization was successful, FALSE otherwise
|
||||
*/
|
||||
public boolean initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this service. If the service returns false on this method then
|
||||
* the service failed to start and may not work as intended.
|
||||
* @return TRUE if starting was successful, FALSE otherwise
|
||||
*/
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the service. If the service returns false on this method then the
|
||||
* service failed to stop and may not have fully locked down.
|
||||
* @return TRUE if stopping was successful, FALSe otherwise
|
||||
*/
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates this service. If the service returns false on this method
|
||||
* then the service failed to shut down and resources may not have been
|
||||
* cleaned up.
|
||||
* @return TRUE if termination was successful, FALSE otherwise
|
||||
*/
|
||||
public boolean terminate() {
|
||||
IntentManager.getInstance().terminate();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not this service is operational
|
||||
* @return TRUE if this service is operational, FALSE otherwise
|
||||
*/
|
||||
public boolean isOperational() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final <T extends Intent> void registerForIntent(Class<T> c, Consumer<T> consumer) {
|
||||
IntentManager.getInstance().registerForIntent(c, (i) -> consumer.accept((T) i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config object associated with a certain file, or NULL if the
|
||||
* file failed to load on startup
|
||||
* @param file the file to get the config for
|
||||
* @return the config object associated with the file, or NULL if the
|
||||
* config failed to load
|
||||
*/
|
||||
public final Config getConfig(ConfigFile file) {
|
||||
return dataManager.getConfig(file);
|
||||
}
|
||||
|
||||
public BackendData getBackendData() {
|
||||
return dataManager.getBackendData();
|
||||
}
|
||||
|
||||
public static void setDataManager(DataManager dataManager) {
|
||||
Service.dataManager = dataManager;
|
||||
}
|
||||
|
||||
public static DataManager getDataManager() {
|
||||
return dataManager;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,10 +33,8 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.data.SQLBuildData;
|
||||
import com.projectswg.common.data.SQLBuildData.BuildInformationBuilder;
|
||||
import com.projectswg.common.data.TestDetails;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.info.RelationalDatabase;
|
||||
import com.projectswg.common.info.RelationalServerFactory;
|
||||
|
||||
|
||||
@@ -33,9 +33,8 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.data.SQLDeploymentData;
|
||||
import com.projectswg.common.data.SQLDeploymentData.DeploymentInformationBuilder;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.info.RelationalDatabase;
|
||||
import com.projectswg.common.info.RelationalServerFactory;
|
||||
|
||||
|
||||
@@ -116,16 +116,16 @@ public class HeavyweightBackendData implements BackendData {
|
||||
try (BuildHistoryTable buildTable = new BuildHistoryTable(db)) {
|
||||
for (SQLBuildData info : buildTable.getBuildHistory(server.getName())) {
|
||||
ServerBuildData build = createBuildFromInfo(server, info);
|
||||
fetchDeploymentHistory(db, server, build);
|
||||
server.addBuild(build);
|
||||
}
|
||||
}
|
||||
fetchDeploymentHistory(db, server);
|
||||
}
|
||||
|
||||
private void fetchDeploymentHistory(RelationalDatabase db, ServerServerData server, ServerBuildData build) {
|
||||
private void fetchDeploymentHistory(RelationalDatabase db, ServerServerData server) {
|
||||
try (DeploymentTable deploymentTable = new DeploymentTable(db)) {
|
||||
for (SQLDeploymentData info : deploymentTable.getDeployments(server.getName())) {
|
||||
ServerDeploymentData deployment = createDeploymentFromInfo(build, info);
|
||||
ServerDeploymentData deployment = createDeploymentFromInfo(server, info);
|
||||
server.addDeployment(deployment);
|
||||
}
|
||||
}
|
||||
@@ -151,8 +151,8 @@ public class HeavyweightBackendData implements BackendData {
|
||||
return build;
|
||||
}
|
||||
|
||||
private ServerDeploymentData createDeploymentFromInfo(ServerBuildData build, SQLDeploymentData info) {
|
||||
ServerDeploymentData deployment = new ServerDeploymentData(info.getId(), build);
|
||||
private ServerDeploymentData createDeploymentFromInfo(ServerServerData server, SQLDeploymentData info) {
|
||||
ServerDeploymentData deployment = new ServerDeploymentData(info.getId(), server.getBuild(info.getBuildId()));
|
||||
deployment.setStartTime(info.getStartTime());
|
||||
deployment.setEndTime(info.getEndTime());
|
||||
return deployment;
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.info.RelationalDatabase;
|
||||
import com.projectswg.common.info.RelationalServerFactory;
|
||||
|
||||
|
||||
@@ -1,183 +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.common.info;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Reads and stores configuration data from a file
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
private final ConfigData configData;
|
||||
|
||||
/**
|
||||
* Initilizes the Config and loads the data in the file
|
||||
* @param filename the file to load
|
||||
*/
|
||||
public Config(String filename) {
|
||||
this(new File(filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initilizes the Config and loads the data in the file
|
||||
* @param file the file to load
|
||||
*/
|
||||
public Config(File file) {
|
||||
if (!file.exists() || !file.isFile())
|
||||
throw new IllegalArgumentException("Filepath does not point to a valid file!");
|
||||
configData = new ConfigData(file);
|
||||
load();
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the key-value pair exists in the config
|
||||
* @param key the key to check
|
||||
* @return TRUE if the key-value pair exists, FALSE otherwise
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
return configData.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter with the specified key. If no such parameter exists,
|
||||
* it returns the default
|
||||
* @param key the key to get the value for
|
||||
* @param def the default value
|
||||
* @return the value represented by the key, or the default value
|
||||
*/
|
||||
public String getString(String key, String def) {
|
||||
if (!containsKey(key)) {
|
||||
setProperty(key, def);
|
||||
return def;
|
||||
}
|
||||
return configData.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter with the specified key. If no such parameter exists,
|
||||
* or if the value isn't an integer then it returns the default
|
||||
* @param key the key to get the value for
|
||||
* @param def the default value
|
||||
* @return the value represented by the key, or the default value
|
||||
*/
|
||||
public int getInt(String key, int def) {
|
||||
try {
|
||||
return Integer.parseInt(getString(key, Integer.toString(def)));
|
||||
} catch (NumberFormatException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter with the specified key. If no such parameter exists,
|
||||
* or if the value isn't a double then it returns the default
|
||||
* @param key the key to get the value for
|
||||
* @param def the default value
|
||||
* @return the value represented by the key, or the default value
|
||||
*/
|
||||
public double getDouble(String key, double def) {
|
||||
try {
|
||||
return Double.parseDouble(getString(key, Double.toString(def)));
|
||||
} catch (NumberFormatException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter with the specified key. If no such parameter exists,
|
||||
* or if the value isn't a boolean then it returns the default
|
||||
* @param key the key to get the value for
|
||||
* @param def the default value
|
||||
* @return the value represented by the key, or the default value
|
||||
*/
|
||||
public boolean getBoolean(String key, boolean def) {
|
||||
String val = getString(key, def?"true":"false");
|
||||
if (val.equalsIgnoreCase("true") || val.equals("1"))
|
||||
return true;
|
||||
if (val.equalsIgnoreCase("false") || val.equals("0"))
|
||||
return false;
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value for the specified key
|
||||
* @param key the key of the value to set
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setProperty(String key, String value) {
|
||||
configData.put(key, value);
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value for the specified key
|
||||
* @param key the key of the value to set
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setProperty(String key, int value) {
|
||||
setProperty(key, Integer.toString(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value for the specified key
|
||||
* @param key the key of the value to set
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setProperty(String key, boolean value) {
|
||||
setProperty(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property value for the specified key
|
||||
* @param key the key of the value to set
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setProperty(String key, double value) {
|
||||
setProperty(key, Double.toString(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the config data from the file
|
||||
* @return TRUE if the data was successfully loaded, FALSE otherwise
|
||||
*/
|
||||
public Map<String, String> load() {
|
||||
return configData.load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the config data to the file
|
||||
* @return TRUE if the data was successfully saved, FALSE otherwise
|
||||
*/
|
||||
public boolean save() {
|
||||
return configData.save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,152 +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.common.info;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class ConfigData {
|
||||
|
||||
private final DateFormat FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss zzz");
|
||||
private final Map<String, String> data;
|
||||
private final File file;
|
||||
|
||||
public ConfigData(File file) {
|
||||
this.data = new TreeMap<>();
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public boolean containsKey(String key) {
|
||||
synchronized (data) {
|
||||
return data.containsKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
synchronized (data) {
|
||||
return data.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
public String put(String key, String value) {
|
||||
synchronized (data) {
|
||||
return data.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null on an I/O failure, an empty {@code Map} on the first load and
|
||||
* a populated {@code Map} when called afterwards
|
||||
*/
|
||||
public Map<String, String> load() {
|
||||
Map<String, String> delta = new HashMap<>();
|
||||
BufferedReader reader = null;
|
||||
|
||||
synchronized (data) {
|
||||
delta.putAll(data); // Copy the current data
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
|
||||
String line = reader.readLine();
|
||||
while (line != null) {
|
||||
loadLine(line);
|
||||
line = reader.readLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
return null;
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Entry<String, String> entry : data.entrySet())
|
||||
delta.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
public boolean save() {
|
||||
BufferedWriter writer = null;
|
||||
synchronized (data) {
|
||||
try {
|
||||
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
|
||||
writer.write("# "+FORMAT.format(System.currentTimeMillis()));
|
||||
writer.newLine();
|
||||
for (Entry <String, String> e : data.entrySet()) {
|
||||
writer.write(e.getKey() + "=" + e.getValue());
|
||||
writer.newLine();
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
return false;
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLine(String line) {
|
||||
String beforeComment = line;
|
||||
if (line.contains("#"))
|
||||
beforeComment = line.substring(0, line.indexOf('#'));
|
||||
if (!beforeComment.contains("="))
|
||||
return;
|
||||
String key = beforeComment.substring(0, beforeComment.indexOf('='));
|
||||
String val = beforeComment.substring(key.length()+1);
|
||||
synchronized (data) {
|
||||
data.put(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.data.HeavyweightBackendData;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.debug.log_wrapper.FileLogWrapper;
|
||||
|
||||
public class HeavyweightDataManager implements DataManager {
|
||||
|
||||
@@ -51,8 +53,13 @@ public class HeavyweightDataManager implements DataManager {
|
||||
if (initialized.getAndSet(true))
|
||||
return;
|
||||
initializeConfig();
|
||||
if (getConfig(ConfigFile.LIGHTSPEED).getBoolean("ENABLE-LOGGING", true))
|
||||
Log.start();
|
||||
if (getConfig(ConfigFile.LIGHTSPEED).getBoolean("ENABLE-LOGGING", true)) {
|
||||
try {
|
||||
Log.addWrapper(new FileLogWrapper(new File("log.txt")));
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void terminate() {
|
||||
|
||||
@@ -50,7 +50,6 @@ public class LightweightDataManager implements DataManager {
|
||||
if (initialized.getAndSet(true))
|
||||
return;
|
||||
setupConfigs();
|
||||
Log.start();
|
||||
}
|
||||
|
||||
public synchronized void terminate() {
|
||||
|
||||
@@ -1,258 +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.common.info;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class Log {
|
||||
|
||||
private static final DateFormat LOG_FORMAT = new SimpleDateFormat("dd-MM-yy HH:mm:ss.SSS");
|
||||
private static final Log LOG = new Log("log.txt", LogLevel.VERBOSE);
|
||||
|
||||
private final File file;
|
||||
private BufferedWriter writer;
|
||||
private LogLevel level;
|
||||
private boolean open;
|
||||
|
||||
private Log(String filename, LogLevel level) {
|
||||
this.file = new File(filename);
|
||||
this.level = level;
|
||||
open = false;
|
||||
}
|
||||
|
||||
private synchronized void open() throws IOException {
|
||||
if (!open)
|
||||
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
|
||||
open = true;
|
||||
}
|
||||
|
||||
private synchronized void close() throws IOException {
|
||||
if (open)
|
||||
writer.close();
|
||||
open = false;
|
||||
}
|
||||
|
||||
private synchronized void write(String str) throws IOException {
|
||||
if (open) {
|
||||
writer.write(str);
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void setLevel(LogLevel level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
private synchronized LogLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
protected static final void start() {
|
||||
try {
|
||||
LOG.open();
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final void stop() {
|
||||
try {
|
||||
LOG.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum level for logs to be reported. This is according to the
|
||||
* following order: VERBOSE, DEBUG, INFO, WARNING, ERROR, then ASSERT.
|
||||
* @param level the minimum log level, inclusively. Default is VERBOSE
|
||||
*/
|
||||
public static final void setLogLevel(LogLevel level) {
|
||||
synchronized (LOG) {
|
||||
LOG.setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity, time and message.
|
||||
* @param level the log level of this message between VERBOSE and ASSERT
|
||||
* @param tag the tag to use for the log
|
||||
* @param str the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void log(LogLevel level, String str, Object ... args) {
|
||||
synchronized (LOG) {
|
||||
if (LOG.getLevel().compareTo(level) > 0)
|
||||
return;
|
||||
}
|
||||
String date;
|
||||
synchronized (LOG_FORMAT) {
|
||||
date = LOG_FORMAT.format(System.currentTimeMillis());
|
||||
}
|
||||
String logStr = String.format(str, args);
|
||||
String log = String.format("%s %c: %s", date, level.getChar(), logStr);
|
||||
if (level.compareTo(LogLevel.WARN) >= 0)
|
||||
System.err.println(date + " " + level.getChar() + ": " + logStr);
|
||||
else
|
||||
System.out.println(date + " " + level.getChar() + ": " + logStr);
|
||||
synchronized (LOG) {
|
||||
try {
|
||||
LOG.write(log);
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as VERBOSE, as well as the time and message.
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void v(String message, Object ... args) {
|
||||
log(LogLevel.VERBOSE, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as DEBUG, as well as the time and message.
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void d(String message, Object ... args) {
|
||||
log(LogLevel.DEBUG, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as INFO, as well as the time and message.
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void i(String message, Object ... args) {
|
||||
log(LogLevel.INFO, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as WARN, as well as the time and message.
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void w(String message, Object ... args) {
|
||||
log(LogLevel.WARN, message, args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs the exception to the server log file, formatted to display the log
|
||||
* severity as WARN, as well as the time, and tag.
|
||||
* @param exception the exception to print
|
||||
*/
|
||||
public static final void w(Throwable exception) {
|
||||
printException(LogLevel.WARN, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as ERROR, as well as the time and message.
|
||||
* @param tag the tag to use for the log
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void e(String message, Object ... args) {
|
||||
log(LogLevel.ERROR, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the exception to the server log file, formatted to display the log
|
||||
* severity as ERROR, as well as the time, and tag.
|
||||
* @param exception the exception to print
|
||||
*/
|
||||
public static final void e(Throwable exception) {
|
||||
printException(LogLevel.ERROR, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the string to the server log file, formatted to display the log
|
||||
* severity as ASSERT, as well as the time and message.
|
||||
* @param message the format string for the log
|
||||
* @param args the string format arguments, if specified
|
||||
*/
|
||||
public static final void a(String message, Object ... args) {
|
||||
log(LogLevel.ASSERT, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the exception to the server log file, formatted to display the log
|
||||
* severity as ASSERT, as well as the time, and tag.
|
||||
* @param exception the exception to print
|
||||
*/
|
||||
public static final void a(Throwable exception) {
|
||||
printException(LogLevel.ASSERT, exception);
|
||||
}
|
||||
|
||||
private static final void printException(LogLevel level, Throwable exception) {
|
||||
synchronized (LOG) {
|
||||
log(level, "Exception in thread\"%s\" %s: %s", Thread.currentThread().getName(), exception.getClass().getName(), exception.getMessage());
|
||||
log(level, "Caused by: %s: %s", exception.getClass(), exception.getMessage());
|
||||
for (StackTraceElement e : exception.getStackTrace()) {
|
||||
log(level, " " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static enum LogLevel {
|
||||
VERBOSE ('V'),
|
||||
DEBUG ('D'),
|
||||
INFO ('I'),
|
||||
WARN ('W'),
|
||||
ERROR ('E'),
|
||||
ASSERT ('A');
|
||||
|
||||
private char c;
|
||||
|
||||
LogLevel(char c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public char getChar() { return c; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,190 +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.common.info;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public abstract class RelationalDatabase implements Closeable {
|
||||
|
||||
private DatabaseMetaData metaData;
|
||||
private Connection connection;
|
||||
private boolean online;
|
||||
|
||||
protected RelationalDatabase(String jdbcClass, String url) {
|
||||
try {
|
||||
Class.forName(jdbcClass);
|
||||
initialize(url);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(e);
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected RelationalDatabase(String jdbcClass, String url, String user, String pass) {
|
||||
try {
|
||||
Class.forName(jdbcClass);
|
||||
initialize(url, user, pass);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(e);
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
public RelationalDatabase(String jdbcClass, String url, String user, String pass, String params) {
|
||||
try {
|
||||
Class.forName(jdbcClass);
|
||||
if (params != null && params.length() > 0)
|
||||
url += "?" + params;
|
||||
initialize(url, user, pass);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(e);
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
public RelationalDatabase(String jdbcClass, String type, String host, String db, String user, String pass, String params) {
|
||||
try {
|
||||
Class.forName(jdbcClass);
|
||||
String url = "jdbc:" + type + "://" + host + "/" + db;
|
||||
if (params != null && params.length() > 0)
|
||||
url += "?" + params;
|
||||
initialize(url, user, pass);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(e);
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initialize(String url) {
|
||||
try {
|
||||
connection = DriverManager.getConnection(url);
|
||||
metaData = connection.getMetaData();
|
||||
online = true;
|
||||
} catch (SQLException e) {
|
||||
Log.e("RelationalDatabase", "Failed to initialize relational database! %s - %s", e.getClass().getSimpleName(), e.getMessage());
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initialize(String url, String user, String pass) {
|
||||
try {
|
||||
connection = DriverManager.getConnection(url, user, pass);
|
||||
metaData = connection.getMetaData();
|
||||
online = true;
|
||||
} catch (SQLException e) {
|
||||
Log.e("RelationalDatabase", "Failed to initialize relational database! %s - %s", e.getClass().getSimpleName(), e.getMessage());
|
||||
online = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
online = false;
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
if (connection == null)
|
||||
return false;
|
||||
try {
|
||||
return online && !connection.isClosed();
|
||||
} catch (SQLException e) {
|
||||
return online;
|
||||
}
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql) {
|
||||
if (connection == null) {
|
||||
Log.e("RelationalDatabase", "Cannot prepare statement! Connection is null");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return connection.prepareStatement(sql);
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ResultSet executeQuery(String query) {
|
||||
if (connection == null)
|
||||
return null;
|
||||
Statement s = null;
|
||||
try {
|
||||
s = connection.createStatement();
|
||||
s.execute(query);
|
||||
try {
|
||||
s.closeOnCompletion();
|
||||
} catch (SQLFeatureNotSupportedException e) {
|
||||
// It was worth a shot
|
||||
}
|
||||
return s.getResultSet();
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
if (s != null) {
|
||||
try { s.close(); } catch (SQLException ex) { }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int updateQuery(String query) {
|
||||
if (connection == null)
|
||||
return 0;
|
||||
try {
|
||||
try (Statement s = connection.createStatement()) {
|
||||
return s.executeUpdate(query);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTable(String name) {
|
||||
if (metaData == null)
|
||||
return false;
|
||||
try {
|
||||
return metaData.getTables(null, null, name, null).next();
|
||||
} catch (SQLException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,445 +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.common.info;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RelationalServerData extends RelationalDatabase {
|
||||
|
||||
private static final Charset ASCII = Charset.forName("ASCII");
|
||||
|
||||
private static final String META_TABLE = "__server_table_metadata__";
|
||||
private final PreparedStatement getTableMetadata;
|
||||
private final PreparedStatement updateTableMetadata;
|
||||
private final PreparedStatement insertTableMetadata;
|
||||
|
||||
public RelationalServerData(String file) {
|
||||
super("org.sqlite.JDBC", "jdbc:sqlite:" + file);
|
||||
/*
|
||||
* GREATLY speeds up INSERT speeds. This makes it so SQLite will not
|
||||
* wait until the previous write finishes before starting to write the
|
||||
* next INSERT. All imports will only take milliseconds. A caveat of
|
||||
* this is that if the power ever cuts or the application is force
|
||||
* killed it may result in database corruption.
|
||||
*/
|
||||
updateQuery("PRAGMA synchronous=OFF");
|
||||
updateQuery("CREATE TABLE IF NOT EXISTS "+META_TABLE+" (table_name TEXT, last_imported INTEGER)");
|
||||
getTableMetadata = prepareStatement("SELECT * FROM "+META_TABLE+" WHERE table_name=?");
|
||||
updateTableMetadata = prepareStatement("UPDATE "+META_TABLE+" SET last_imported=? WHERE table_name=?");
|
||||
insertTableMetadata = prepareStatement("INSERT INTO "+META_TABLE+" (table_name, last_imported) VALUES (?, ?)");
|
||||
}
|
||||
|
||||
public boolean linkTableWithSdb(String table, String filepath) {
|
||||
File sdb = new File(filepath);
|
||||
if (!sdb.isFile())
|
||||
return false;
|
||||
if (testLastModified(table, sdb) || testMasterSdbModified(table, sdb)) {
|
||||
updateQuery("DROP TABLE IF EXISTS " + table);
|
||||
importFromSdb(table, sdb);
|
||||
updateLastImported(table, System.currentTimeMillis());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean testLastModified(String table, File sdb) {
|
||||
return sdb.lastModified() > getLastImported(table);
|
||||
}
|
||||
|
||||
private boolean testMasterSdbModified(String table, File sdb) {
|
||||
if (!sdb.getName().endsWith(".msdb"))
|
||||
return false;
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sdb), ASCII))) {
|
||||
reader.readLine();
|
||||
reader.readLine();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (testLastModified(table, new File(sdb.getParent(), line.substring(0, line.indexOf('\t')))))
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a record with the specified information into the database
|
||||
* @param table the table to insert into
|
||||
* @param columns the columns to insert into
|
||||
* @param params the parameters to insert
|
||||
* @return TRUE on success, FALSE on failure
|
||||
* @throws SQLException upon error
|
||||
*/
|
||||
public boolean insert(String table, String [] columns, Object ... params) throws SQLException {
|
||||
StringBuilder columnStr = new StringBuilder("");
|
||||
StringBuilder valuesStr = new StringBuilder("");
|
||||
if (columns == null)
|
||||
columns = getColumnsForTable(table);
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
columnStr.append(columns[i]);
|
||||
valuesStr.append('?');
|
||||
if (i+1 < columns.length) {
|
||||
columnStr.append(',');
|
||||
valuesStr.append(',');
|
||||
}
|
||||
}
|
||||
final String sql = String.format("INSERT INTO %s (%s) VALUES (%s)", table, columnStr, valuesStr);
|
||||
try (PreparedStatement statement = prepareStatement(sql)) {
|
||||
if (statement == null || params.length < getSqlParameterCount(sql))
|
||||
return false;
|
||||
assignParameters(statement, params);
|
||||
return statement.executeUpdate() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects from the specified table with the supplied where clause, given
|
||||
* the supplied parameters
|
||||
* @param tables the tables to query, separated by commas
|
||||
* @param columns the columns to select, null to select all
|
||||
* @param where the where clause
|
||||
* @param params the parameters to put into the ?s in the where clause
|
||||
* @return the result set
|
||||
* @throws SQLException upon error
|
||||
*/
|
||||
public ResultSet selectFromTable(String tables, String [] columns, String where, Object ... params) throws SQLException {
|
||||
final String sql = createSelectQuery(tables, columns, where, params);
|
||||
PreparedStatement statement = prepareStatement(sql);
|
||||
if (statement == null || params.length < getSqlParameterCount(sql))
|
||||
return null;
|
||||
assignParameters(statement, params);
|
||||
return statement.executeQuery();
|
||||
}
|
||||
|
||||
private void assignParameters(PreparedStatement statement, Object ... params) throws SQLException {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (params[i] instanceof Integer || params[i] instanceof Long)
|
||||
statement.setLong(i+1, ((Number) params[i]).longValue());
|
||||
else if (params[i] instanceof Float || params[i] instanceof Double)
|
||||
statement.setDouble(i+1, ((Number) params[i]).doubleValue());
|
||||
else if (params[i] instanceof String)
|
||||
statement.setString(i+1, (String) params[i]);
|
||||
else if (params[i] != null)
|
||||
throw new IllegalArgumentException("Unknown object type: " + params[i].getClass().getSimpleName());
|
||||
else
|
||||
throw new NullPointerException("Parameters cannot have null elements!");
|
||||
}
|
||||
}
|
||||
|
||||
private int getSqlParameterCount(String sql) {
|
||||
int ret = 0;
|
||||
for (int i = 0; i < sql.length(); i++) {
|
||||
if (sql.charAt(i) == '?')
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String createSelectQuery(String tables, String [] columns, String where, Object ... params) {
|
||||
String columnStr = "*";
|
||||
if (columns == null && tables.contains(",")) {
|
||||
StringBuilder bldr = new StringBuilder("");
|
||||
for (String table : tables.split(",")) {
|
||||
bldr.append(table.trim());
|
||||
bldr.append(".*, ");
|
||||
}
|
||||
columnStr = bldr.substring(0, columnStr.length()-2);
|
||||
} else if (columns != null) {
|
||||
StringBuilder bldr = new StringBuilder("");
|
||||
for (String column : columns) {
|
||||
bldr.append(column);
|
||||
bldr.append(", ");
|
||||
}
|
||||
columnStr = bldr.substring(0, bldr.length()-2);
|
||||
}
|
||||
return "SELECT " + columnStr + " FROM " + tables + " WHERE " + where;
|
||||
}
|
||||
|
||||
private String [] getColumnsForTable(String table) throws SQLException {
|
||||
List<String> columns = new ArrayList<>();
|
||||
try (ResultSet set = executeQuery("PRAGMA table_info('"+table+"')")) {
|
||||
int colInd = set.findColumn("name");
|
||||
while (set.next()) {
|
||||
columns.add(set.getString(colInd));
|
||||
}
|
||||
}
|
||||
return columns.toArray(new String[columns.size()]);
|
||||
}
|
||||
|
||||
private long getLastImported(String table) {
|
||||
synchronized (getTableMetadata) {
|
||||
ResultSet set = null;
|
||||
try {
|
||||
getTableMetadata.setString(1, table);
|
||||
set = getTableMetadata.executeQuery();
|
||||
if (set.next())
|
||||
return set.getLong("last_imported");
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
} finally {
|
||||
if (set != null) {
|
||||
try {
|
||||
set.close();
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLastImported(String table, long lastImported) {
|
||||
synchronized (updateTableMetadata) {
|
||||
try {
|
||||
updateTableMetadata.setLong(1, lastImported);
|
||||
updateTableMetadata.setString(2, table);
|
||||
if (updateTableMetadata.executeUpdate() > 0)
|
||||
return;
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
synchronized (insertTableMetadata) {
|
||||
try {
|
||||
insertTableMetadata.setString(1, table);
|
||||
insertTableMetadata.setLong(2, lastImported);
|
||||
insertTableMetadata.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean importFromSdb(String table, File sdb) {
|
||||
try (TableReader reader = new TableReader(table, sdb)) {
|
||||
Log.i("RelationalServerData", "Importing sdb... '" + sdb + "'");
|
||||
if (sdb.getName().endsWith(".msdb"))
|
||||
reader.readMaster();
|
||||
else
|
||||
reader.readNormal();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e("RelationalServerData", "Invalid file format. Aborting read of %s! Message: %s", sdb, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class TableReader implements Closeable {
|
||||
|
||||
private final String table;
|
||||
private final File file;
|
||||
private String [] columnNames;
|
||||
private String [] columnTypes;
|
||||
private PreparedStatement insert;
|
||||
|
||||
public TableReader(String table, File file) {
|
||||
this.table = table;
|
||||
this.file = file;
|
||||
this.columnNames = null;
|
||||
this.columnTypes = null;
|
||||
this.insert = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (insert != null) {
|
||||
try {
|
||||
insert.close();
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readNormal() throws IOException, SQLException {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), ASCII))) {
|
||||
readNormalRemainder(reader, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void readMaster() throws SQLException, IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), ASCII))) {
|
||||
int lineNum = 1;
|
||||
readLine(reader.readLine(), lineNum++);
|
||||
readLine(reader.readLine(), lineNum++);
|
||||
readMasterRemainder(reader, lineNum);
|
||||
}
|
||||
}
|
||||
|
||||
private void readSlave() throws IOException, SQLException {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), ASCII))) {
|
||||
int lineNum = 3;
|
||||
reader.readLine();
|
||||
reader.readLine(); // Skip column names and types
|
||||
readNormalRemainder(reader, lineNum);
|
||||
}
|
||||
}
|
||||
|
||||
private void readMasterRemainder(BufferedReader reader, int lineNum) throws IOException, SQLException {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String [] parts = line.split("\t");
|
||||
if (parts.length != 2) {
|
||||
Log.e("RelationalServerData", "Invalid line [%d]: %s", lineNum, line);
|
||||
continue;
|
||||
}
|
||||
boolean load = Boolean.parseBoolean(parts[1]);
|
||||
if (load) {
|
||||
File sdb = new File(file.getParent(), parts[0]);
|
||||
Log.i("RelationalServerData", " Importing sdb... '" + sdb + "'");
|
||||
if (!sdb.isFile()) {
|
||||
Log.e("RelationalServerData", " Failed to import sdb! File is not file or does not exist");
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("resource") // This closes the database.. we don't want to do that yet
|
||||
TableReader slave = new TableReader(table, sdb);
|
||||
slave.columnNames = columnNames;
|
||||
slave.columnTypes = columnTypes;
|
||||
slave.insert = insert;
|
||||
slave.readSlave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readNormalRemainder(BufferedReader reader, int lineNum) throws IOException, SQLException {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
readLine(line, lineNum++);
|
||||
}
|
||||
if (insert != null)
|
||||
insert.executeBatch();
|
||||
}
|
||||
|
||||
private void readLine(String line, int lineNum) throws SQLException {
|
||||
if (line == null)
|
||||
return;
|
||||
switch (lineNum) {
|
||||
case 1:
|
||||
columnNames = fastTabSplit(line);
|
||||
break;
|
||||
case 2:
|
||||
columnTypes = fastTabSplit(line);
|
||||
createTable();
|
||||
createPreparedStatement();
|
||||
break;
|
||||
default:
|
||||
generateInsert(fastTabSplit(line), lineNum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String [] fastTabSplit(String str) {
|
||||
int count = 1;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (str.charAt(i) == '\t') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
String [] tabs = new String[count];
|
||||
int tabInd = 0;
|
||||
int prevInd = 0;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (str.charAt(i) == '\t') {
|
||||
tabs[tabInd++] = str.substring(prevInd, i);
|
||||
prevInd = i+1;
|
||||
}
|
||||
}
|
||||
if (prevInd < str.length())
|
||||
tabs[tabInd++] = str.substring(prevInd);
|
||||
return tabs;
|
||||
}
|
||||
|
||||
private void createTable() {
|
||||
if (columnNames.length != columnTypes.length)
|
||||
throw new IllegalArgumentException("Names length and types length mismatch");
|
||||
StringBuilder sql = new StringBuilder("CREATE TABLE "+table+" (");
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
if (i > 0)
|
||||
sql.append(", ");
|
||||
sql.append(columnNames[i]);
|
||||
sql.append(' ');
|
||||
sql.append(columnTypes[i]);
|
||||
}
|
||||
sql.append(')');
|
||||
updateQuery(sql.toString());
|
||||
}
|
||||
|
||||
private void createPreparedStatement() {
|
||||
StringBuilder sql = new StringBuilder("INSERT INTO " + table + " VALUES (");
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
if (i > 0)
|
||||
sql.append(", ");
|
||||
sql.append('?');
|
||||
}
|
||||
sql.append(')');
|
||||
insert = prepareStatement(sql.toString());
|
||||
}
|
||||
|
||||
private void generateInsert(String [] data, int line) throws SQLException {
|
||||
if (columnTypes.length != data.length) {
|
||||
Log.e("RelationalServerData", "Could not load record: Types length and data length mismatch. Line: " + line);
|
||||
return;
|
||||
}
|
||||
int column = 0;
|
||||
try {
|
||||
for (int i = 0; i < data.length; i++, column++) {
|
||||
if (columnTypes[i].startsWith("TEXT"))
|
||||
insert.setString(i+1, data[i]);
|
||||
else if (columnTypes[i].startsWith("REAL"))
|
||||
insert.setDouble(i+1, Double.parseDouble(data[i]));
|
||||
else if (columnTypes[i].startsWith("INTEGER"))
|
||||
insert.setLong(i+1, Long.parseLong(data[i]));
|
||||
else
|
||||
throw new SQLException("Data type unsupported by sdb/sqlite! Type: " + columnTypes[i]);
|
||||
}
|
||||
insert.addBatch();
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e("RelationalServerData", "Could not load record: Record has invalid data. Line: " + line + " Column: " + column);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,271 +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.common.info;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RelationalServerFactory {
|
||||
|
||||
private static final RelationalServerFactory INSTANCE = new RelationalServerFactory();
|
||||
private static final String BASE_PATH = "data" + File.separator;
|
||||
private static final Map <String, Object> FILE_LOAD_LOCKING = new HashMap<>();
|
||||
|
||||
public static RelationalServerData getServerData(String file, String ... tables) {
|
||||
return INSTANCE.getData(file, tables);
|
||||
}
|
||||
|
||||
public static RelationalServerData getServerDatabase(String file) {
|
||||
return INSTANCE.getDatabase(file);
|
||||
}
|
||||
|
||||
private RelationalServerData getData(String file, String ... tables) {
|
||||
if (!file.endsWith(".db"))
|
||||
throw new IllegalArgumentException("File path for database must end in .db!");
|
||||
file = file.replace('/', File.separatorChar);
|
||||
final Object lock = getFileLocking(file);
|
||||
synchronized (lock) {
|
||||
File f = new File(BASE_PATH + file);
|
||||
RelationalServerData data = new RelationalServerData(BASE_PATH + file);
|
||||
if (loadServerData(data, f, tables))
|
||||
return data;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadServerData(RelationalServerData data, File file, String ... tables) {
|
||||
File parent = file.getParentFile();
|
||||
try {
|
||||
if (loadTables(data, parent, tables))
|
||||
return true;
|
||||
data.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
data.close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private RelationalServerData getDatabase(String file) {
|
||||
if (!file.endsWith(".db"))
|
||||
throw new IllegalArgumentException("File path for database must end in .db!");
|
||||
final Object lock = getFileLocking(file);
|
||||
synchronized (lock) {
|
||||
File f = new File(BASE_PATH + file);
|
||||
RelationalServerData data = new RelationalServerData(BASE_PATH + file);
|
||||
try {
|
||||
String [] commands = getCommandsFromSchema(f.getPath().substring(0, f.getPath().length()-3) + ".sql");
|
||||
ParserData parserData = new ParserData();
|
||||
for (String command : commands)
|
||||
executeCommand(data, command, parserData);
|
||||
return data;
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
}
|
||||
data.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadTables(RelationalServerData data, File parent, String [] tables) {
|
||||
for (String table : tables) {
|
||||
table = table.replace('/', File.separatorChar);
|
||||
String path = generatePath(parent, table);
|
||||
table = path.substring(path.lastIndexOf(File.separatorChar)+1, path.lastIndexOf('.'));
|
||||
if (!data.linkTableWithSdb(table, path))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String generatePath(File parent, String table) {
|
||||
String base;
|
||||
if (table.contains(File.separator))
|
||||
base = BASE_PATH + table;
|
||||
else
|
||||
base = parent.getPath() + File.separator + table;
|
||||
if (new File(base + ".msdb").isFile())
|
||||
return base + ".msdb";
|
||||
return base + ".sdb";
|
||||
}
|
||||
|
||||
private void executeCommand(RelationalServerData data, String command, ParserData parserData) {
|
||||
command = command.trim();
|
||||
if (command.startsWith("SELECT") && parserData.getConditional()) {
|
||||
try (ResultSet set = data.executeQuery(command)) {
|
||||
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
} else if (command.startsWith("IF")) { // VERY SIMPLE 'if' logic, no parenthesis and no AND/OR's - expects 3 arguments: <num/var> <op> <num/var>
|
||||
parserData.addConditional(evaluateIf(data, command.substring(2).trim()));
|
||||
} else if (command.startsWith("ENDIF")) {
|
||||
parserData.unwrapLastConditional();
|
||||
} else if (parserData.getConditional()) {
|
||||
data.updateQuery(command);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean evaluateIf(RelationalServerData data, String statement) {
|
||||
String [] args = statement.split(" ", 3);
|
||||
if (args.length != 3) {
|
||||
Log.e("Invalid IF statement: %s", statement);
|
||||
return false;
|
||||
}
|
||||
double num1 = parseToNumber(data, args[0]);
|
||||
String comparator = args[1];
|
||||
double num2 = parseToNumber(data, args[2]);
|
||||
switch (comparator) {
|
||||
case "<": return num1 < num2;
|
||||
case ">": return num1 > num2;
|
||||
case "=": return num1 == num2;
|
||||
case "==": return num1 == num2;
|
||||
case "<=": return num1 <= num2;
|
||||
case ">=": return num1 >= num2;
|
||||
default:
|
||||
Log.e("Invalid comparator: %s", comparator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private double parseToNumber(RelationalServerData data, String str) {
|
||||
if (str.equals("user_version")) {
|
||||
ResultSet set = data.executeQuery("PRAGMA user_version");
|
||||
try {
|
||||
if (set.next())
|
||||
return set.getDouble(1);
|
||||
else
|
||||
Log.e("Variable 'user_version' has not been set!");
|
||||
} catch (SQLException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return Double.parseDouble(str);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e("Number '%s' is not a valid number!", str);
|
||||
}
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
private String [] getCommandsFromSchema(String schema) throws IOException {
|
||||
String command;
|
||||
try (InputStream input = new FileInputStream(new File(schema))) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(input.available());
|
||||
byte [] block = new byte[1024];
|
||||
while (input.available() > 0) {
|
||||
int size = input.read(block);
|
||||
baos.write(block, 0, size);
|
||||
}
|
||||
command = new String(baos.toByteArray(), Charset.forName("ASCII"));
|
||||
}
|
||||
return command.split(";");
|
||||
}
|
||||
|
||||
private Object getFileLocking(String file) {
|
||||
synchronized (FILE_LOAD_LOCKING) {
|
||||
Object o = FILE_LOAD_LOCKING.get(file);
|
||||
if (o == null)
|
||||
FILE_LOAD_LOCKING.put(file, o = new Object());
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ParserData {
|
||||
|
||||
private RecursiveBoolean conditionalValue;
|
||||
|
||||
public ParserData() {
|
||||
conditionalValue = null;
|
||||
}
|
||||
|
||||
public void addConditional(boolean val) {
|
||||
if (conditionalValue == null)
|
||||
conditionalValue = new RecursiveBoolean(val);
|
||||
else
|
||||
conditionalValue.createRecursive(val);
|
||||
}
|
||||
|
||||
public void unwrapLastConditional() {
|
||||
if (conditionalValue != null && conditionalValue.unwrapLast())
|
||||
conditionalValue = null;
|
||||
}
|
||||
|
||||
public boolean getConditional() {
|
||||
if (conditionalValue == null)
|
||||
return true;
|
||||
return conditionalValue.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RecursiveBoolean {
|
||||
|
||||
private final boolean val;
|
||||
private RecursiveBoolean recursive;
|
||||
|
||||
public RecursiveBoolean(boolean val) {
|
||||
this.val = val;
|
||||
this.recursive = null;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
if (recursive != null)
|
||||
return val && recursive.get();
|
||||
return val;
|
||||
}
|
||||
|
||||
public RecursiveBoolean createRecursive(boolean val) {
|
||||
if (recursive != null)
|
||||
return recursive.createRecursive(val);
|
||||
return (recursive = new RecursiveBoolean(val));
|
||||
}
|
||||
|
||||
public boolean unwrapLast() {
|
||||
RecursiveBoolean recur = this;
|
||||
while (recur.recursive != null && recur.recursive.recursive != null)
|
||||
recur = recur.recursive;
|
||||
if (recur != null && recur.recursive != null) {
|
||||
recur.recursive = null;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,237 +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.common.network;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
public class NetBuffer {
|
||||
|
||||
public static final Charset ASCII = Charset.forName("UTF-8");
|
||||
public static final Charset UNICODE = Charset.forName("UTF-16LE");
|
||||
|
||||
private final ByteBuffer data;
|
||||
private final int size;
|
||||
|
||||
private NetBuffer(ByteBuffer data) {
|
||||
this.data = data;
|
||||
this.size = data.array().length;
|
||||
}
|
||||
|
||||
public static final NetBuffer allocate(int size) {
|
||||
return new NetBuffer(ByteBuffer.allocate(size));
|
||||
}
|
||||
|
||||
public static final NetBuffer wrap(byte [] data) {
|
||||
return new NetBuffer(ByteBuffer.wrap(data));
|
||||
}
|
||||
|
||||
public static final NetBuffer wrap(ByteBuffer data) {
|
||||
return new NetBuffer(data);
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
return data.remaining();
|
||||
}
|
||||
|
||||
public int position() {
|
||||
return data.position();
|
||||
}
|
||||
|
||||
public void position(int position) {
|
||||
data.position(position);
|
||||
}
|
||||
|
||||
public void seek(int relative) {
|
||||
data.position(data.position()+relative);
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void addBoolean(boolean b) {
|
||||
data.put(b ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
public void addAscii(String s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putShort((short)s.length());
|
||||
data.put(s.getBytes(ASCII));
|
||||
}
|
||||
|
||||
public void addAscii(char [] s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putShort((short)s.length);
|
||||
ByteBuffer bb = ASCII.encode(CharBuffer.wrap(s));
|
||||
byte [] bData = new byte[bb.limit()];
|
||||
bb.get(bData);
|
||||
data.put(bData);
|
||||
}
|
||||
|
||||
public void addUnicode(String s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putInt(s.length());
|
||||
data.put(s.getBytes(UNICODE));
|
||||
}
|
||||
|
||||
public void addLong(long l) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN).putLong(l);
|
||||
}
|
||||
|
||||
public void addInt(int i) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN).putInt(i);
|
||||
}
|
||||
|
||||
public void addFloat(float f) {
|
||||
data.putFloat(f);
|
||||
}
|
||||
|
||||
public void addShort(int i) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN).putShort((short)i);
|
||||
}
|
||||
|
||||
public void addNetLong(long l) {
|
||||
data.order(ByteOrder.BIG_ENDIAN).putLong(l);
|
||||
}
|
||||
|
||||
public void addNetInt(int i) {
|
||||
data.order(ByteOrder.BIG_ENDIAN).putInt(i);
|
||||
}
|
||||
|
||||
public void addNetShort(int i) {
|
||||
data.order(ByteOrder.BIG_ENDIAN).putShort((short)i);
|
||||
}
|
||||
|
||||
public void addByte(int b) {
|
||||
data.put((byte)b);
|
||||
}
|
||||
|
||||
public void addArray(byte [] b) {
|
||||
addShort(b.length);
|
||||
data.put(b);
|
||||
}
|
||||
|
||||
public void addRawArray(byte [] b) {
|
||||
data.put(b);
|
||||
}
|
||||
|
||||
public boolean getBoolean() {
|
||||
return getByte() == 1 ? true : false;
|
||||
}
|
||||
|
||||
public String getAscii() {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
short length = data.getShort();
|
||||
if (length > data.remaining())
|
||||
return "";
|
||||
byte [] str = new byte[length];
|
||||
data.get(str);
|
||||
return new String(str, ASCII);
|
||||
}
|
||||
|
||||
public String getUnicode() {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int length = data.getInt() * 2;
|
||||
if (length > data.remaining())
|
||||
return "";
|
||||
byte [] str = new byte[length];
|
||||
data.get(str);
|
||||
return new String(str, UNICODE);
|
||||
}
|
||||
|
||||
public byte getByte() {
|
||||
return data.get();
|
||||
}
|
||||
|
||||
public short getShort() {
|
||||
return data.order(ByteOrder.LITTLE_ENDIAN).getShort();
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return data.order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
}
|
||||
|
||||
public float getFloat() {
|
||||
return data.getFloat();
|
||||
}
|
||||
|
||||
public long getLong() {
|
||||
return data.order(ByteOrder.LITTLE_ENDIAN).getLong();
|
||||
}
|
||||
|
||||
public short getNetShort() {
|
||||
return data.order(ByteOrder.BIG_ENDIAN).getShort();
|
||||
}
|
||||
|
||||
public int getNetInt() {
|
||||
return data.order(ByteOrder.BIG_ENDIAN).getInt();
|
||||
}
|
||||
|
||||
public long getNetLong() {
|
||||
return data.order(ByteOrder.BIG_ENDIAN).getLong();
|
||||
}
|
||||
|
||||
public byte [] getArray() {
|
||||
byte [] bData = new byte[getShort()];
|
||||
data.get(bData);
|
||||
return bData;
|
||||
}
|
||||
|
||||
public byte [] getArray(int size) {
|
||||
byte [] bData = new byte[size];
|
||||
data.get(bData);
|
||||
return bData;
|
||||
}
|
||||
|
||||
public byte [] array() {
|
||||
return data.array();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public byte [] copyArray() {
|
||||
return copyArray(0, size);
|
||||
}
|
||||
|
||||
public byte [] copyArray(int offset, int length) {
|
||||
if (length < 0)
|
||||
throw new IllegalArgumentException("Length cannot be less than 0!");
|
||||
if (offset+length > size)
|
||||
throw new IllegalArgumentException("Length extends past the end of the array!");
|
||||
byte [] ret = new byte[length];
|
||||
System.arraycopy(array(), offset, ret, 0, length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,435 +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.common.network;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class NetBufferStream extends OutputStream {
|
||||
|
||||
private final Object expansionMutex;
|
||||
private final Object bufferMutex;
|
||||
private NetBuffer buffer;
|
||||
private int capacity;
|
||||
private int size;
|
||||
private int mark;
|
||||
|
||||
public NetBufferStream() {
|
||||
this(1024);
|
||||
}
|
||||
|
||||
public NetBufferStream(int size) {
|
||||
if (size <= 0)
|
||||
throw new NegativeArraySizeException("Size cannot be less than or equal to 0!");
|
||||
this.expansionMutex = new Object();
|
||||
this.bufferMutex = new Object();
|
||||
this.buffer = NetBuffer.allocate(size);
|
||||
this.capacity = size;
|
||||
this.size = 0;
|
||||
this.mark = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mark to the buffer's current position
|
||||
*/
|
||||
public void mark() {
|
||||
synchronized (bufferMutex) {
|
||||
mark = buffer.position();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds the buffer to the previously set mark
|
||||
*/
|
||||
public void rewind() {
|
||||
synchronized (bufferMutex) {
|
||||
buffer.position(mark);
|
||||
mark = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the buffer to the default capacity and clears all data
|
||||
*/
|
||||
public void reset() {
|
||||
synchronized (expansionMutex) {
|
||||
synchronized (bufferMutex) {
|
||||
buffer = NetBuffer.allocate(1024);
|
||||
capacity = 1024;
|
||||
size = 0;
|
||||
mark = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
ensureCapacity(size + 1);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.array()[size] = (byte) b;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
public void write(byte [] data) {
|
||||
write(data, 0, data.length);
|
||||
}
|
||||
|
||||
public void write(byte [] data, int offset, int length) {
|
||||
ensureCapacity(size + length);
|
||||
synchronized (bufferMutex) {
|
||||
System.arraycopy(data, offset, buffer.array(), size, length);
|
||||
size += length;
|
||||
}
|
||||
}
|
||||
|
||||
public void write(ByteBuffer data) {
|
||||
ensureCapacity(size + data.remaining());
|
||||
synchronized (bufferMutex) {
|
||||
while (data.hasRemaining()) {
|
||||
buffer.array()[size++] = data.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves all data from the buffer's current position to position 0. This
|
||||
* method also adjusts the mark to be pointing to the same data
|
||||
*/
|
||||
public void compact() {
|
||||
synchronized (bufferMutex) {
|
||||
byte [] data = buffer.array();
|
||||
for (int i = buffer.position(), j = 0; i < size; ++i, ++j) {
|
||||
data[j] = data[i];
|
||||
}
|
||||
size -= buffer.position();
|
||||
mark -= buffer.position();
|
||||
buffer.position(0);
|
||||
}
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
synchronized (bufferMutex) {
|
||||
return size - buffer.position();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasRemaining() {
|
||||
return remaining() > 0;
|
||||
}
|
||||
|
||||
public int position() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.position();
|
||||
}
|
||||
}
|
||||
|
||||
public void position(int position) {
|
||||
synchronized (bufferMutex) {
|
||||
buffer.position(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void seek(int relative) {
|
||||
synchronized (bufferMutex) {
|
||||
buffer.seek(relative);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getBoolean() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
public String getAscii() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getAscii();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnicode() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getUnicode();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getByte() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getByte();
|
||||
}
|
||||
}
|
||||
|
||||
public short getShort() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getShort();
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getInt();
|
||||
}
|
||||
}
|
||||
|
||||
public float getFloat() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getFloat();
|
||||
}
|
||||
}
|
||||
|
||||
public long getLong() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getLong();
|
||||
}
|
||||
}
|
||||
|
||||
public short getNetShort() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getNetShort();
|
||||
}
|
||||
}
|
||||
|
||||
public int getNetInt() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getNetInt();
|
||||
}
|
||||
}
|
||||
|
||||
public long getNetLong() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getNetLong();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getArray() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getArray();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getArray(int size) {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.getArray(size);
|
||||
}
|
||||
}
|
||||
|
||||
public void getList(NumericalIterator ni) {
|
||||
int size = getInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
ni.onItem(i);
|
||||
}
|
||||
|
||||
public void addBoolean(boolean b) {
|
||||
ensureCapacity(size+1);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addBoolean(b);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
public void addAscii(String s) {
|
||||
ensureCapacity(size+2+s.length());
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addAscii(s);
|
||||
size += 2 + s.length();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAscii(char[] s) {
|
||||
ensureCapacity(size+2+s.length);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addAscii(s);
|
||||
size += 2 + s.length;
|
||||
}
|
||||
}
|
||||
|
||||
public void addUnicode(String s) {
|
||||
ensureCapacity(size+4+s.length()*2);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addUnicode(s);
|
||||
size += 4 + s.length()*2;
|
||||
}
|
||||
}
|
||||
|
||||
public void addLong(long l) {
|
||||
ensureCapacity(size+8);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addLong(l);
|
||||
size += 8;
|
||||
}
|
||||
}
|
||||
|
||||
public void addInt(int i) {
|
||||
ensureCapacity(size+4);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addInt(i);
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void addFloat(float f) {
|
||||
ensureCapacity(size+4);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addFloat(f);
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void addShort(int i) {
|
||||
ensureCapacity(size+2);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addShort(i);
|
||||
size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void addNetLong(long l) {
|
||||
ensureCapacity(size+8);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addNetLong(l);
|
||||
size += 8;
|
||||
}
|
||||
}
|
||||
|
||||
public void addNetInt(int i) {
|
||||
ensureCapacity(size+4);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addNetInt(i);
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void addNetShort(int i) {
|
||||
ensureCapacity(size+2);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addNetShort(i);
|
||||
size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void addByte(int b) {
|
||||
ensureCapacity(size+1);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addByte(b);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
public void addArray(byte[] b) {
|
||||
ensureCapacity(size+2+b.length);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addArray(b);
|
||||
size += 2 + b.length;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void addList(List<T> l, ListIterable<T> r) {
|
||||
addInt(l.size());
|
||||
for (T t : l)
|
||||
r.onItem(t);
|
||||
}
|
||||
|
||||
public <T> void addList(Set<T> s, ListIterable<T> r) {
|
||||
addInt(s.size());
|
||||
for (T t : s)
|
||||
r.onItem(t);
|
||||
}
|
||||
|
||||
public <K, V> void addMap(Map<K, V> m, MapIterable<K, V> r) {
|
||||
addInt(m.size());
|
||||
for (Entry<K, V> e : m.entrySet())
|
||||
r.onItem(e);
|
||||
}
|
||||
|
||||
public void addRawArray(byte[] b) {
|
||||
write(b);
|
||||
}
|
||||
|
||||
public byte [] array() {
|
||||
synchronized (bufferMutex) {
|
||||
return buffer.array();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int size) {
|
||||
if (size <= capacity)
|
||||
return;
|
||||
synchronized (expansionMutex) {
|
||||
while (size > capacity)
|
||||
capacity <<= 2;
|
||||
synchronized (bufferMutex) {
|
||||
NetBuffer buf = NetBuffer.allocate(capacity);
|
||||
System.arraycopy(buffer.array(), 0, buf.array(), 0, this.size);
|
||||
buf.position(buffer.position());
|
||||
this.buffer = buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ListIterable<T> {
|
||||
void onItem(T item);
|
||||
}
|
||||
|
||||
public static interface MapIterable<K, V> {
|
||||
void onItem(Entry<K, V> item);
|
||||
}
|
||||
|
||||
public static interface NumericalIterator {
|
||||
void onItem(int index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,298 +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.common.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.callback.CallbackManager;
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
|
||||
public class TCPServer {
|
||||
|
||||
private final CallbackManager<TCPCallback> callbackManager;
|
||||
private final Map<SocketAddress, SocketChannel> sockets;
|
||||
private final AtomicBoolean running;
|
||||
private final InetAddress addr;
|
||||
private final int port;
|
||||
private final int bufferSize;
|
||||
private ServerSocketChannel channel;
|
||||
private TCPListener listener;
|
||||
|
||||
public TCPServer(int port, int bufferSize) {
|
||||
this(null, port, bufferSize);
|
||||
}
|
||||
|
||||
public TCPServer(InetAddress addr, int port, int bufferSize) {
|
||||
this.callbackManager = new CallbackManager<>("tcpserver-"+port, 1);
|
||||
this.sockets = new HashMap<>();
|
||||
this.running = new AtomicBoolean(false);
|
||||
this.addr = addr;
|
||||
this.port = port;
|
||||
this.bufferSize = bufferSize;
|
||||
this.channel = null;
|
||||
listener = new TCPListener();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return channel.socket().getLocalPort();
|
||||
}
|
||||
|
||||
public void bind() throws IOException {
|
||||
if (running.getAndSet(true)) {
|
||||
Assert.fail();
|
||||
return;
|
||||
}
|
||||
callbackManager.start();
|
||||
channel = ServerSocketChannel.open();
|
||||
channel.socket().bind(new InetSocketAddress(addr, port));
|
||||
channel.configureBlocking(false);
|
||||
listener.start();
|
||||
}
|
||||
|
||||
public SocketChannel connectTo(InetAddress addr, int port) throws IOException {
|
||||
return connectTo(new InetSocketAddress(addr, port));
|
||||
}
|
||||
|
||||
public SocketChannel connectTo(InetSocketAddress sock) throws IOException {
|
||||
Assert.notNull(sock);
|
||||
synchronized (sockets) {
|
||||
SocketChannel sc = sockets.get(sock);
|
||||
if (sc == null || (!sc.isConnected() && !sc.isConnectionPending())) {
|
||||
sc = SocketChannel.open(sock);
|
||||
sc.configureBlocking(false);
|
||||
sockets.put(sock, sc);
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean disconnect(SocketAddress sock) {
|
||||
Assert.notNull(sock);
|
||||
synchronized (sockets) {
|
||||
SocketChannel sc = sockets.get(sock);
|
||||
Assert.notNull(sc);
|
||||
sockets.remove(sock);
|
||||
try {
|
||||
Socket s = sc.socket();
|
||||
sc.close();
|
||||
callbackManager.callOnEach((callback) -> callback.onConnectionDisconnect(s, sock));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean disconnect(SocketChannel sc) {
|
||||
try {
|
||||
return disconnect(sc.getRemoteAddress());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean close() {
|
||||
if (!running.getAndSet(false)) {
|
||||
Assert.fail();
|
||||
return false;
|
||||
}
|
||||
callbackManager.stop();
|
||||
listener.stop();
|
||||
try {
|
||||
channel.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean send(InetSocketAddress sock, ByteBuffer data) {
|
||||
synchronized (sockets) {
|
||||
SocketChannel sc = sockets.get(sock);
|
||||
Assert.notNull(sc);
|
||||
Assert.test(sc.isConnected());
|
||||
Assert.test(data.hasRemaining());
|
||||
try {
|
||||
if (sc != null && sc.isConnected()) {
|
||||
while (data.hasRemaining())
|
||||
sc.write(data);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("TCPServer", "Terminated connection with %s. Error: %s", sock.toString(), e.getMessage());
|
||||
disconnect(sc);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setCallback(TCPCallback callback) {
|
||||
callbackManager.setCallback(callback);
|
||||
}
|
||||
|
||||
public interface TCPCallback {
|
||||
void onIncomingConnection(Socket s);
|
||||
void onConnectionDisconnect(Socket s, SocketAddress addr);
|
||||
void onIncomingData(Socket s, byte [] data);
|
||||
}
|
||||
|
||||
private class TCPListener implements Runnable {
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
private Thread thread;
|
||||
private boolean running;
|
||||
|
||||
public TCPListener() {
|
||||
buffer = ByteBuffer.allocateDirect(bufferSize);
|
||||
running = false;
|
||||
thread = null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
running = true;
|
||||
thread = new Thread(this, "TCPServer port " + channel.socket().getLocalPort());
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
if (thread != null)
|
||||
thread.interrupt();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try (Selector selector = setupSelector()) {
|
||||
while (running) {
|
||||
try {
|
||||
selector.select();
|
||||
processSelectionKeys(selector);
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Selector setupSelector() throws IOException {
|
||||
Selector selector = Selector.open();
|
||||
channel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
return selector;
|
||||
}
|
||||
|
||||
private void processSelectionKeys(Selector selector) throws ClosedChannelException {
|
||||
for (SelectionKey key : selector.selectedKeys()) {
|
||||
if (!key.isValid())
|
||||
continue;
|
||||
if (key.isAcceptable()) {
|
||||
accept(selector);
|
||||
} else if (key.isReadable()) {
|
||||
SelectableChannel selectable = key.channel();
|
||||
if (selectable instanceof SocketChannel) {
|
||||
boolean canRead = true;
|
||||
while (canRead)
|
||||
canRead = read(key, (SocketChannel) selectable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void accept(Selector selector) {
|
||||
try {
|
||||
while (channel.isOpen()) {
|
||||
SocketChannel sc = channel.accept();
|
||||
if (sc == null)
|
||||
break;
|
||||
SocketChannel old = sockets.get(sc.getRemoteAddress());
|
||||
if (old != null)
|
||||
disconnect(old);
|
||||
sockets.put(sc.getRemoteAddress(), sc);
|
||||
sc.configureBlocking(false);
|
||||
sc.register(selector, SelectionKey.OP_READ);
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingConnection(sc.socket()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean read(SelectionKey key, SocketChannel s) {
|
||||
try {
|
||||
buffer.position(0);
|
||||
buffer.limit(bufferSize);
|
||||
int n = s.read(buffer);
|
||||
buffer.flip();
|
||||
if (n < 0) {
|
||||
key.cancel();
|
||||
disconnect(s);
|
||||
} else if (n > 0) {
|
||||
ByteBuffer smaller = ByteBuffer.allocate(n);
|
||||
smaller.put(buffer);
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingData(s.socket(), smaller.array()));
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e.getMessage() != null && e.getMessage().toLowerCase(Locale.US).contains("connection reset"))
|
||||
Log.e("TCPServer", "Connection Reset with %s", s.socket().getRemoteSocketAddress());
|
||||
else if (!(e instanceof ClosedByInterruptException))
|
||||
Log.e("TCPServer", e);
|
||||
key.cancel();
|
||||
disconnect(s);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,172 +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.common.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.callback.CallbackManager;
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
public class TCPSocket {
|
||||
|
||||
private final InetSocketAddress address;
|
||||
private final TCPSocketListener listener;
|
||||
private final CallbackManager<TCPSocketCallback> callbackManager;
|
||||
private final int bufferSize;
|
||||
private SocketChannel socket;
|
||||
|
||||
public TCPSocket(InetSocketAddress address, int bufferSize) {
|
||||
this.address = address;
|
||||
this.listener = new TCPSocketListener();
|
||||
this.bufferSize = bufferSize;
|
||||
this.callbackManager = new CallbackManager<>("tcpsocket-"+address, 1);
|
||||
this.socket = null;
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setCallback(TCPSocketCallback callback) {
|
||||
callbackManager.setCallback(callback);
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
disconnect();
|
||||
try {
|
||||
callbackManager.start();
|
||||
socket = SocketChannel.open(address);
|
||||
listener.start();
|
||||
callbackManager.callOnEach((callback) -> callback.onConnected(this));
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
callbackManager.callOnEach((callback) -> callback.onDisconnected(this));
|
||||
callbackManager.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean disconnect() {
|
||||
if (socket == null)
|
||||
return true;
|
||||
try {
|
||||
callbackManager.stop();
|
||||
socket.close();
|
||||
listener.stop();
|
||||
callbackManager.callOnEach((callback) -> callback.onDisconnected(this));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean send(ByteBuffer data) {
|
||||
try {
|
||||
while (data.hasRemaining()) {
|
||||
if (socket == null || socket.write(data) <= 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public interface TCPSocketCallback {
|
||||
void onConnected(TCPSocket socket);
|
||||
void onDisconnected(TCPSocket socket);
|
||||
void onIncomingData(TCPSocket socket, byte [] data);
|
||||
}
|
||||
|
||||
private class TCPSocketListener implements Runnable {
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private final AtomicBoolean alive = new AtomicBoolean(false);
|
||||
private Thread thread;
|
||||
|
||||
public void start() {
|
||||
stop();
|
||||
awaitTermination();
|
||||
thread = new Thread(this);
|
||||
running.set(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running.set(false);
|
||||
if (thread != null)
|
||||
thread.interrupt();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
public void awaitTermination() {
|
||||
while (alive.get()) {
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
alive.set(true);
|
||||
SocketChannel sc = TCPSocket.this.socket;
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(TCPSocket.this.bufferSize);
|
||||
if (sc == null)
|
||||
return;
|
||||
try {
|
||||
while (running.get()) {
|
||||
buf.position(0);
|
||||
buf.limit(bufferSize);
|
||||
int n = sc.read(buf);
|
||||
buf.flip();
|
||||
if (n > 0) {
|
||||
byte [] data = new byte[n];
|
||||
buf.position(0);
|
||||
buf.get(data, 0, n);
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingData(TCPSocket.this, data));
|
||||
} else
|
||||
disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
disconnect();
|
||||
} finally {
|
||||
running.set(false);
|
||||
alive.set(false);
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.network.packets;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.network.packets.post.*;
|
||||
import com.projectswg.common.network.packets.request.*;
|
||||
import com.projectswg.common.network.packets.response.*;
|
||||
@@ -64,6 +64,11 @@ public class Packet {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LightspeedPacket["+type+"]";
|
||||
}
|
||||
|
||||
public static JSONObject createPacketJson(PacketType type) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("type", type.name());
|
||||
|
||||
@@ -29,10 +29,9 @@ 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;
|
||||
|
||||
public class PostBuildPacket extends Packet {
|
||||
public class PostBuildPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
|
||||
@@ -29,11 +29,10 @@ 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 com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
|
||||
public class PostCreateServerPacket extends Packet {
|
||||
public class PostCreateServerPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
private static final String DIRECTORY = "directory";
|
||||
|
||||
@@ -29,10 +29,9 @@ 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;
|
||||
|
||||
public class PostDeleteServerPacket extends Packet {
|
||||
public class PostDeleteServerPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
|
||||
@@ -29,10 +29,9 @@ 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;
|
||||
|
||||
public class PostDeployPacket extends Packet {
|
||||
public class PostDeployPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
|
||||
+13
-4
@@ -25,12 +25,21 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.info;
|
||||
package com.projectswg.common.network.packets.post;
|
||||
|
||||
public class PostgresqlDatabase extends RelationalDatabase {
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
public abstract class PostPacket extends Packet {
|
||||
|
||||
public PostgresqlDatabase(String host, String db, String user, String pass) {
|
||||
super("org.postgresql.Driver", "postgresql", host, db, user, pass, "");
|
||||
public PostPacket(JSONObject json, PacketType type) {
|
||||
super(json, type);
|
||||
}
|
||||
|
||||
public PostPacket(PacketType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,10 +29,9 @@ 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;
|
||||
|
||||
public class PostStopBuildPacket extends Packet {
|
||||
public class PostStopBuildPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
|
||||
@@ -29,10 +29,9 @@ 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;
|
||||
|
||||
public class PostStopDeployPacket extends Packet {
|
||||
public class PostStopDeployPacket extends PostPacket {
|
||||
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
|
||||
@@ -1,51 +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.common.network.protocol;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
|
||||
public abstract class Protocol {
|
||||
|
||||
private final String version;
|
||||
|
||||
protected Protocol(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public abstract ByteBuffer preparePacket(Packet p);
|
||||
public abstract void onIncomingData(byte [] data);
|
||||
public abstract Packet getNextPacket();
|
||||
public abstract int getPacketCount();
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +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.common.network.protocol;
|
||||
|
||||
public class ProtocolFactory {
|
||||
|
||||
public static Protocol createProtocol(String version) {
|
||||
if (version == null)
|
||||
return new AlphaProtocol();
|
||||
switch (version) {
|
||||
case AlphaProtocol.VERSION: return new AlphaProtocol();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +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.common.utilities;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
public class ThreadUtilities {
|
||||
|
||||
public static ThreadFactory newThreadFactory(String pattern) {
|
||||
return new CustomThreadFactory(pattern);
|
||||
}
|
||||
|
||||
private static class CustomThreadFactory implements ThreadFactory {
|
||||
|
||||
private final String pattern;
|
||||
private int counter;
|
||||
|
||||
public CustomThreadFactory(String pattern) {
|
||||
this.pattern = pattern;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
String name;
|
||||
if (pattern.contains("%d"))
|
||||
name = String.format(pattern, counter++);
|
||||
else
|
||||
name = pattern;
|
||||
return new Thread(r, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +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.common.utilities;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
public class TimeUtilities {
|
||||
|
||||
private static final String DATE_TIME_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
|
||||
private static final TimeZone CURRENT_TIMEZONE = TimeZone.getDefault();
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
private static final DateFormat DATE_TIME_FORMATTER_CUR = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.US);
|
||||
private static final DateFormat DATE_TIME_FORMATTER_UTC = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.US);
|
||||
|
||||
static {
|
||||
DATE_TIME_FORMATTER_UTC.setTimeZone(UTC);
|
||||
}
|
||||
|
||||
public static long getTime() {
|
||||
return System.currentTimeMillis() - CURRENT_TIMEZONE.getOffset(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static long getTime(long offset, TimeUnit unit) {
|
||||
return getTime() + unit.toMillis(offset);
|
||||
}
|
||||
|
||||
public static String getDateStringUtc(long time) {
|
||||
synchronized (DATE_TIME_FORMATTER_UTC) {
|
||||
return DATE_TIME_FORMATTER_UTC.format(time);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDateString(long time) {
|
||||
synchronized (DATE_TIME_FORMATTER_CUR) {
|
||||
return DATE_TIME_FORMATTER_CUR.format(time);
|
||||
}
|
||||
}
|
||||
|
||||
public static long getTimeFromStringUtc(String str) {
|
||||
synchronized (DATE_TIME_FORMATTER_UTC) {
|
||||
try {
|
||||
return DATE_TIME_FORMATTER_UTC.parse(str).getTime();
|
||||
} catch (ParseException e) {
|
||||
Log.e(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static long getTimeFromString(String str) {
|
||||
synchronized (DATE_TIME_FORMATTER_CUR) {
|
||||
try {
|
||||
return DATE_TIME_FORMATTER_CUR.parse(str).getTime();
|
||||
} catch (ParseException e) {
|
||||
Log.e(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static long convertUtcToLocal(long time) {
|
||||
return time + CURRENT_TIMEZONE.getOffset(time);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,11 +36,11 @@ import java.util.Map.Entry;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
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.info.Log;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.lightspeed.communication.HttpResponder;
|
||||
@@ -50,7 +50,7 @@ import fi.iki.elonen.NanoHTTPD.IHTTPSession;
|
||||
import fi.iki.elonen.NanoHTTPD.Response;
|
||||
import fi.iki.elonen.NanoHTTPD.Response.Status;
|
||||
|
||||
public class CommunicationService extends Service {
|
||||
public class CommunicationService extends LightspeedService {
|
||||
|
||||
private final NanoHTTPD httpServer;
|
||||
private final Map<PacketType, HttpResponder> responders;
|
||||
|
||||
@@ -38,14 +38,14 @@ import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import network.packets.swg.admin.AdminShutdownServer;
|
||||
import me.joshlarson.json.JSONObject;
|
||||
import network.packets.swg.admin.AdminShutdownServer;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
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.info.Log;
|
||||
import com.projectswg.common.intents.LaunchStarshipIntent;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
@@ -65,7 +65,7 @@ import com.projectswg.lightspeed.sequenced.SequencedStarter;
|
||||
import com.projectswg.lightspeed.server.ServerServerData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
|
||||
|
||||
public class DeploymentService extends Service {
|
||||
public class DeploymentService extends LightspeedService {
|
||||
|
||||
private final AtomicLong deploymentId;
|
||||
private final Map<String, Deployment> deployments;
|
||||
@@ -130,7 +130,10 @@ public class DeploymentService extends Service {
|
||||
|
||||
private JSONObject processPostDeploy(JSONObject params) {
|
||||
PostDeployPacket deploy = new PostDeployPacket(params);
|
||||
launchStarship(deploy.getServerId());
|
||||
ServerServerData server = getBackendData().getServer(deploy.getServerId());
|
||||
if (server == null)
|
||||
return new PostResult(false).getJSON();
|
||||
launchStarship(server);
|
||||
return new PostResult(true).getJSON();
|
||||
}
|
||||
|
||||
@@ -171,8 +174,7 @@ public class DeploymentService extends Service {
|
||||
return new ResponseDeploymentListPacket(request.getServerId(), deployList).getJSON();
|
||||
}
|
||||
|
||||
private void launchStarship(String serverId) {
|
||||
ServerServerData server = getBackendData().getServer(serverId);
|
||||
private void launchStarship(ServerServerData server) {
|
||||
ServerBuildData build = server.getLastBuild();
|
||||
if (!launchStarshipChecks(build))
|
||||
return;
|
||||
@@ -210,7 +212,7 @@ public class DeploymentService extends Service {
|
||||
return;
|
||||
}
|
||||
ServerDeploymentData deployment = new ServerDeploymentData(deploymentId.incrementAndGet(), build);
|
||||
Log.i("Creating Deployment #%d", deployment.getId());
|
||||
Log.i("Creating Deployment #%d from build #%d and server %s", deployment.getId(), build.getId(), deployment.getServer().getName());
|
||||
Deployment newDeployment = new Deployment(deployment);
|
||||
if (old != null) {
|
||||
old.setReplacement(newDeployment);
|
||||
@@ -304,12 +306,16 @@ public class DeploymentService extends Service {
|
||||
}
|
||||
|
||||
private StarshipProcess prepareProcess(ServerDeploymentData deployment) {
|
||||
String serverId = deployment.getServer().getName();
|
||||
File java = new File(getJdk(), File.separatorChar+"bin"+File.separatorChar+"java");
|
||||
File jar = new File("data"+File.separatorChar+"releases"+File.separatorChar+serverId+".jar");
|
||||
File jar = new File("data"+File.separatorChar+"releases"+File.separatorChar+deployment.getServer().getName()+".jar");
|
||||
File dir = new File(deployment.getServer().getDirectory());
|
||||
String args = deployment.getServer().getJvmArguments();
|
||||
return StarshipProcess.create(java, jar, dir, args, "");
|
||||
String [] command = new String[] {
|
||||
java.getAbsolutePath(),
|
||||
"-jar",
|
||||
jar.getAbsolutePath(),
|
||||
deployment.getServer().getJvmArguments()
|
||||
};
|
||||
return StarshipProcess.create(dir, command);
|
||||
}
|
||||
|
||||
private void onDeploymentStarted(ServerDeploymentData deployment) {
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.lightspeed;
|
||||
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
|
||||
public class GitListenerService extends Service {
|
||||
public class GitListenerService extends LightspeedService {
|
||||
|
||||
public GitListenerService() {
|
||||
|
||||
|
||||
+3
-3
@@ -27,12 +27,12 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.lightspeed;
|
||||
|
||||
import com.projectswg.common.control.Manager;
|
||||
import com.projectswg.common.control.LightspeedManager;
|
||||
import com.projectswg.lightspeed.build.BuildService;
|
||||
import com.projectswg.lightspeed.gui.GUIService;
|
||||
import com.projectswg.lightspeed.server.ServerService;
|
||||
|
||||
public class LightspeedManager extends Manager {
|
||||
public class LightspeedMainManager extends LightspeedManager {
|
||||
|
||||
private final GitListenerService gitListenerService;
|
||||
private final ServerService serverService;
|
||||
@@ -41,7 +41,7 @@ public class LightspeedManager extends Manager {
|
||||
private final CommunicationService communicationService;
|
||||
private final GUIService guiService;
|
||||
|
||||
public LightspeedManager() {
|
||||
public LightspeedMainManager() {
|
||||
gitListenerService = new GitListenerService();
|
||||
serverService = new ServerService();
|
||||
buildService = new BuildService();
|
||||
@@ -33,54 +33,36 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Assert;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.lightspeed.deployment.ServerDeploymentData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
|
||||
|
||||
public class StarshipProcess {
|
||||
|
||||
private final Object processMutex;
|
||||
private final File java;
|
||||
private final File jar;
|
||||
private final File dir;
|
||||
private final String jvmArgs;
|
||||
private final String swgArgs;
|
||||
private final String [] commands;
|
||||
private Process process;
|
||||
private int exitValue;
|
||||
|
||||
private StarshipProcess(File java, File jar, File dir, String jvmArgs, String swgArgs) {
|
||||
if (java == null)
|
||||
throw new NullPointerException("Java cannot be null!");
|
||||
if (jar == null)
|
||||
throw new NullPointerException("Jar cannot be null!");
|
||||
private StarshipProcess(File dir, String [] commands) {
|
||||
if (dir == null)
|
||||
throw new NullPointerException("Directory cannot be null!");
|
||||
if (!java.isFile())
|
||||
throw new IllegalArgumentException("Java does not exist or is not a file!");
|
||||
if (!jar.isFile())
|
||||
throw new IllegalArgumentException("Jar does not exist or is not a file!");
|
||||
if (!dir.isDirectory())
|
||||
throw new IllegalArgumentException("Directory does not exist or is not a directory!");
|
||||
if (commands == null)
|
||||
throw new NullPointerException("");
|
||||
this.processMutex = new Object();
|
||||
this.java = java;
|
||||
this.jar = jar;
|
||||
this.dir = dir;
|
||||
this.jvmArgs = jvmArgs;
|
||||
this.swgArgs = swgArgs;
|
||||
this.commands = new String[commands.length+1];
|
||||
System.arraycopy(commands, 0, this.commands, 0, commands.length);
|
||||
this.commands[commands.length] = "";
|
||||
this.process = null;
|
||||
this.exitValue = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
private ProcessBuilder createBuilder(int adminServerPort) {
|
||||
String adminArg = "-adminServerPort=" + adminServerPort;
|
||||
if (jvmArgs != null && swgArgs != null)
|
||||
return new ProcessBuilder(java.getAbsolutePath(), jvmArgs, "-jar", jar.getAbsolutePath(), swgArgs, adminArg);
|
||||
else if (jvmArgs != null)
|
||||
return new ProcessBuilder(java.getAbsolutePath(), jvmArgs, "-jar", jar.getAbsolutePath(), adminArg);
|
||||
else if (swgArgs != null)
|
||||
return new ProcessBuilder(java.getAbsolutePath(), "-jar", jar.getAbsolutePath(), swgArgs, adminArg);
|
||||
return new ProcessBuilder(java.getAbsolutePath(), "-jar", jar.getAbsolutePath(), adminArg);
|
||||
commands[commands.length-1] = "-adminServerPort=" + adminServerPort;
|
||||
return new ProcessBuilder(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,16 +155,8 @@ public class StarshipProcess {
|
||||
}
|
||||
}
|
||||
|
||||
public static StarshipProcess create(File java, File pswgJar, File dir) {
|
||||
return create(java, pswgJar, dir, null, null);
|
||||
}
|
||||
|
||||
public static StarshipProcess create(File java, File pswgJar, File dir, String jvmArgs, String swgArgs) {
|
||||
if (jvmArgs != null && jvmArgs.trim().isEmpty())
|
||||
jvmArgs = null;
|
||||
if (swgArgs != null && swgArgs.trim().isEmpty())
|
||||
swgArgs = null;
|
||||
return new StarshipProcess(java, pswgJar, dir, jvmArgs, swgArgs);
|
||||
public static StarshipProcess create(File dir, String [] commands) {
|
||||
return new StarshipProcess(dir, commands);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,10 +41,10 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.intents.LaunchStarshipIntent;
|
||||
import com.projectswg.common.intents.PrepareStarshipIntent;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
@@ -61,15 +61,13 @@ import com.projectswg.lightspeed.sequenced.SequencedStarter;
|
||||
import com.projectswg.lightspeed.server.ServerServerData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
|
||||
|
||||
public class BuildService extends Service {
|
||||
public class BuildService extends LightspeedService {
|
||||
|
||||
private final JavaBuildMethod buildMethod;
|
||||
private final AtomicLong buildId;
|
||||
private final Map <String, Build> inprogress;
|
||||
private final Set<ServerBuildData> buildHistory;
|
||||
|
||||
public BuildService() {
|
||||
buildMethod = new JavaBuildMethod(getJdk());
|
||||
buildId = new AtomicLong(0);
|
||||
inprogress = new HashMap<>();
|
||||
buildHistory = new HashSet<>();
|
||||
@@ -112,9 +110,10 @@ public class BuildService extends Service {
|
||||
private void onPrepareStarshipIntent(PrepareStarshipIntent psi) {
|
||||
ServerBuildData buildData = new ServerBuildData(buildId.incrementAndGet(), psi.getServer());
|
||||
Log.i("Creating build #%d", buildData.getId());
|
||||
buildMethod.createJar(buildData, psi.getServer(), new BuildInstallationCallback(psi.getServer().getName(), psi.isRedeploy()));
|
||||
Build build = new Build(buildData);
|
||||
BuildInstallationCallback callback = new BuildInstallationCallback(psi.getServer().getName(), psi.isRedeploy());
|
||||
JavaBuildMethod buildMethod = new JavaBuildMethod(getJdk(), psi.getServer(), buildData, callback);
|
||||
synchronized (inprogress) {
|
||||
Build build = new Build(buildData);
|
||||
Build old = inprogress.put(psi.getServer().getName(), build);
|
||||
if (old != null) {
|
||||
old.setReplacement(build);
|
||||
@@ -123,6 +122,7 @@ public class BuildService extends Service {
|
||||
build.start();
|
||||
}
|
||||
}
|
||||
buildMethod.start();
|
||||
}
|
||||
|
||||
private JSONObject processBuild(JSONObject params) {
|
||||
|
||||
@@ -28,107 +28,103 @@
|
||||
package com.projectswg.lightspeed.build;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.projectswg.common.data.TestDetails;
|
||||
import com.projectswg.common.info.Log;
|
||||
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.CustomJavaBuild;
|
||||
import com.projectswg.lightspeed.build.java_builder.CustomJavaException;
|
||||
import com.projectswg.lightspeed.build.java_builder.CustomJavaInstall;
|
||||
import com.projectswg.lightspeed.build.java_builder.CustomJavaTest;
|
||||
import com.projectswg.lightspeed.build.java_builder.RepoInstaller;
|
||||
import com.projectswg.lightspeed.server.ServerServerData;
|
||||
|
||||
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 final File jdk;
|
||||
private final RepoInstaller installer;
|
||||
private final ServerBuildData buildData;
|
||||
private final InstallationCallback callback;
|
||||
|
||||
public JavaBuildMethod(File jdk) {
|
||||
this.jdk = jdk;
|
||||
public JavaBuildMethod(File jdk, ServerServerData serverData, ServerBuildData buildData, InstallationCallback callback) {
|
||||
this.installer = new RepoInstaller(processRepositoryArgument(serverData.getDirectory()), jdk);
|
||||
this.buildData = buildData;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void createJar(ServerBuildData build, ServerServerData server, InstallationCallback callback) {
|
||||
String repo = server.getDirectory();
|
||||
String processedRepo = processRepositoryArgument(repo);
|
||||
public void start() {
|
||||
new Thread(() -> {
|
||||
createJar(processedRepo, build, callback);
|
||||
}).start();
|
||||
createJar();
|
||||
}, "java-build-"+buildData.getId()).start();
|
||||
}
|
||||
|
||||
private String processRepositoryArgument(String repo) {
|
||||
private File processRepositoryArgument(String repo) {
|
||||
if (repo.endsWith(SEP))
|
||||
return repo.substring(0, repo.length()-1);
|
||||
return repo;
|
||||
return new File(repo.substring(0, repo.length()-1));
|
||||
return new File(repo);
|
||||
}
|
||||
|
||||
private void createJar(String repo, ServerBuildData buildData, InstallationCallback callback) {
|
||||
private void createJar() {
|
||||
try {
|
||||
RepoInstaller installer = new RepoInstaller(new File(repo), jdk);
|
||||
buildData.setTime(TimeUtilities.getTime());
|
||||
if (!build(installer, buildData, callback)) {
|
||||
updateState(buildData, callback, InstallationState.FAILED);
|
||||
return;
|
||||
if (build() && test() && install()) {
|
||||
updateState(InstallationState.SUCCESS);
|
||||
} else {
|
||||
if (buildData.getState() != InstallationState.CANCELLED) {
|
||||
updateState(InstallationState.CANCELLED);
|
||||
}
|
||||
}
|
||||
if (!test(installer, buildData, callback)) {
|
||||
updateState(buildData, callback, InstallationState.FAILED);
|
||||
return;
|
||||
}
|
||||
if (!install(installer, buildData, callback)) {
|
||||
updateState(buildData, callback, InstallationState.FAILED);
|
||||
return;
|
||||
}
|
||||
updateState(buildData, callback, InstallationState.SUCCESS);
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
updateState(buildData, callback, InstallationState.FAILED);
|
||||
updateState(InstallationState.FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean build(RepoInstaller installer, ServerBuildData buildData, InstallationCallback callback) {
|
||||
updateState(buildData, callback, InstallationState.BUILDING);
|
||||
CustomJavaBuild build = new CustomJavaBuild(installer);
|
||||
if (!build.compile(buildData))
|
||||
return false;
|
||||
if (detectCancelled(buildData, callback))
|
||||
return false;
|
||||
return true;
|
||||
private boolean build() {
|
||||
updateState(InstallationState.BUILDING);
|
||||
long start = System.nanoTime();
|
||||
StringBuilder output = new StringBuilder("");
|
||||
boolean success = installer.executeAnt("compile", output);
|
||||
buildData.setBuildSuccess(success);
|
||||
buildData.setBuildString(output.toString());
|
||||
buildData.setCompileTime((System.nanoTime() - start) / 1E6);
|
||||
return success && !detectCancelled(buildData, callback);
|
||||
}
|
||||
|
||||
private boolean test(RepoInstaller installer, ServerBuildData buildData, InstallationCallback callback) {
|
||||
updateState(buildData, callback, InstallationState.TESTING);
|
||||
CustomJavaTest test = new CustomJavaTest(installer);
|
||||
TestDetails details = test.test(buildData);
|
||||
if (details.getFailures() > 0 || details.getTotal() < 0)
|
||||
return false;
|
||||
if (detectCancelled(buildData, callback))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean install(RepoInstaller installer, ServerBuildData buildData, InstallationCallback callback) {
|
||||
updateState(buildData, callback, InstallationState.INSTALLING);
|
||||
try {
|
||||
CustomJavaInstall install = new CustomJavaInstall(installer);
|
||||
install.createRawJar(buildData, "main.ProjectSWG");
|
||||
return true;
|
||||
} catch (CustomJavaException e) {
|
||||
Log.e(e);
|
||||
return false;
|
||||
private boolean test() {
|
||||
updateState(InstallationState.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()) {
|
||||
System.err.println("Failed to match FAIL pattern: " + output);
|
||||
buildData.setTestSuccess(false);
|
||||
buildData.setTestDetails(new TestDetails(0, 0));
|
||||
} else {
|
||||
buildData.setTestSuccess(success);
|
||||
buildData.setTestDetails(new TestDetails(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) + Integer.parseInt(m.group(3))));
|
||||
}
|
||||
buildData.setTestString(output.toString());
|
||||
return buildData.isTestSuccess() && !detectCancelled(buildData, callback);
|
||||
}
|
||||
|
||||
private boolean install() {
|
||||
updateState(InstallationState.INSTALLING);
|
||||
installer.executeAnt("jar", new StringBuilder(""));
|
||||
buildData.setJar(installer.getJar());
|
||||
return !detectCancelled(buildData, callback);
|
||||
}
|
||||
|
||||
private boolean detectCancelled(ServerBuildData buildData, InstallationCallback callback) {
|
||||
if (buildData.getState() == InstallationState.CANCELLED) {
|
||||
updateState(buildData, callback, InstallationState.CANCELLED);
|
||||
updateState(InstallationState.CANCELLED);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateState(ServerBuildData buildData, InstallationCallback callback, InstallationState newState) {
|
||||
private void updateState(InstallationState newState) {
|
||||
InstallationState oldState = buildData.getState();
|
||||
buildData.setState(newState);
|
||||
if (callback != null)
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.io.InputStreamReader;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.lightspeed.build.ServerBuildData.InstallationCallback;
|
||||
|
||||
public class MavenInterface implements BuildMethod {
|
||||
|
||||
@@ -1,52 +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.build.java_builder;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.lightspeed.build.ServerBuildData;
|
||||
|
||||
public class CustomJavaBuild {
|
||||
|
||||
private final RepoInstaller installer;
|
||||
|
||||
public CustomJavaBuild(RepoInstaller installer) {
|
||||
this.installer = installer;
|
||||
}
|
||||
|
||||
public boolean compile(ServerBuildData buildData) {
|
||||
long start = System.nanoTime();
|
||||
StringBuilder output = new StringBuilder("");
|
||||
boolean success = installer.executeAnt("compile", output);
|
||||
buildData.setBuildSuccess(success);
|
||||
buildData.setBuildString(output.toString());
|
||||
buildData.setCompileTime((System.nanoTime() - start) / 1E6);
|
||||
Log.i("Output: %s", output.toString());
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
|
||||
|
||||
public class CustomJavaCommon {
|
||||
|
||||
|
||||
@@ -1,45 +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.build.java_builder;
|
||||
|
||||
import com.projectswg.lightspeed.build.ServerBuildData;
|
||||
|
||||
public class CustomJavaInstall {
|
||||
|
||||
private final RepoInstaller installer;
|
||||
|
||||
public CustomJavaInstall(RepoInstaller installer) {
|
||||
this.installer = installer;
|
||||
}
|
||||
|
||||
public void createRawJar(ServerBuildData buildData, String file) throws CustomJavaException {
|
||||
installer.executeAnt("jar", new StringBuilder(""));
|
||||
buildData.setJar(installer.getJar());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +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.build.java_builder;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.projectswg.common.data.TestDetails;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.lightspeed.build.ServerBuildData;
|
||||
|
||||
public class CustomJavaTest {
|
||||
|
||||
private static final Pattern JUNIT_PATTERN = Pattern.compile("Tests run: (\\d+), Failures: (\\d+), Errors: (\\d+).*$");
|
||||
|
||||
private final RepoInstaller installer;
|
||||
|
||||
public CustomJavaTest(RepoInstaller installer) {
|
||||
this.installer = installer;
|
||||
}
|
||||
|
||||
public TestDetails test(ServerBuildData buildData) {
|
||||
StringBuilder output = new StringBuilder("");
|
||||
boolean success = installer.executeAnt("test", output);
|
||||
TestDetails details = parseFail(output.toString());
|
||||
buildData.setTestSuccess(success);
|
||||
buildData.setTestString(output.toString());
|
||||
buildData.setTestDetails(details);
|
||||
Log.i("Output: %s", output.toString());
|
||||
return details;
|
||||
}
|
||||
|
||||
private TestDetails parseFail(String out) {
|
||||
String line = out.substring(out.indexOf("Tests run"), out.indexOf('\n', out.indexOf("Tests run")));
|
||||
Matcher m = JUNIT_PATTERN.matcher(line);
|
||||
if (!m.matches()) {
|
||||
System.err.println("Failed to match FAIL pattern: " + line);
|
||||
return new TestDetails(-1, 0);
|
||||
}
|
||||
return new TestDetails(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) + Integer.parseInt(m.group(3)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,8 @@ import org.apache.tools.ant.BuildListener;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.ProjectHelper;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
|
||||
|
||||
public class RepoInstaller {
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
|
||||
|
||||
public class GitInterface {
|
||||
|
||||
@@ -55,7 +56,7 @@ public class GitInterface {
|
||||
return "";
|
||||
return qa.getObjectId().getName();
|
||||
} catch (GitAPIException e) {
|
||||
Log.e(e);
|
||||
Log.e("Failed to query last commit from repository [%s]: %s", repository, e.getMessage());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -69,7 +70,7 @@ public class GitInterface {
|
||||
.setProgressMonitor(new CustomProgressMonitor()).call();
|
||||
return res.isSuccessful();
|
||||
} catch (GitAPIException e) {
|
||||
Log.e(e);
|
||||
Log.e("Failed to pull from repository [%s]: %s", repository, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ import javafx.application.Application;
|
||||
|
||||
import com.projectswg.Lightspeed;
|
||||
import com.projectswg.common.concurrency.PswgBasicThread;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
|
||||
public class GUIService extends Service {
|
||||
public class GUIService extends LightspeedService {
|
||||
|
||||
private final PswgBasicThread guiThread;
|
||||
private boolean headless;
|
||||
|
||||
@@ -32,7 +32,8 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
|
||||
|
||||
public abstract class SequencedStarter {
|
||||
|
||||
|
||||
@@ -95,6 +95,10 @@ public class ServerServerData {
|
||||
return builds.lastEntry().getValue();
|
||||
}
|
||||
|
||||
public ServerBuildData getBuild(long buildId) {
|
||||
return builds.get(buildId);
|
||||
}
|
||||
|
||||
public List<ServerBuildData> getBuilds() {
|
||||
return new ArrayList<>(builds.values());
|
||||
}
|
||||
@@ -105,6 +109,10 @@ public class ServerServerData {
|
||||
return deployments.lastEntry().getValue();
|
||||
}
|
||||
|
||||
public ServerDeploymentData getDeployment(long deploymentId) {
|
||||
return deployments.get(deploymentId);
|
||||
}
|
||||
|
||||
public List<ServerDeploymentData> getDeployments() {
|
||||
return new ArrayList<>(deployments.values());
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ import java.util.Set;
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.control.LightspeedService;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.intents.PrepareStarshipIntent;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
@@ -49,7 +49,7 @@ import com.projectswg.common.network.packets.response.ResponseServerListPacket;
|
||||
import com.projectswg.lightspeed.git.GitInterface;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
|
||||
public class ServerService extends Service {
|
||||
public class ServerService extends LightspeedService {
|
||||
|
||||
private final Set<ServerServerData> servers;
|
||||
private final PswgBasicScheduledThread gitScanner;
|
||||
@@ -75,7 +75,7 @@ public class ServerService extends Service {
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
gitScanner.startWithFixedDelay(30000, 15000);
|
||||
gitScanner.startWithFixedDelay(15000, 15000);
|
||||
return super.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,63 +28,99 @@
|
||||
package com.projectswg.lightspeed_frontend;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.info.Log;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
|
||||
import com.projectswg.common.concurrency.PswgThreadPool;
|
||||
import com.projectswg.common.data.TestDetails;
|
||||
import com.projectswg.common.debug.Assert;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
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.ResponsePacket;
|
||||
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 com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedData;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication.ResponseCallback;
|
||||
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.intents.InboundPacketIntent;
|
||||
|
||||
public class Frontend {
|
||||
|
||||
private final PswgThreadPool threadPool;
|
||||
private final PswgScheduledThreadPool scheduledUpdater;
|
||||
private final FrontendCommunication communication;
|
||||
private final SharedData data;
|
||||
private final FrontendData data;
|
||||
|
||||
public Frontend() {
|
||||
communication = new FrontendCommunication();
|
||||
data = new SharedData();
|
||||
this.threadPool = new PswgThreadPool(10, "frontend-thread-pool");
|
||||
this.scheduledUpdater = new PswgScheduledThreadPool(1, "frontend-updater");
|
||||
this.communication = new FrontendCommunication();
|
||||
this.communication.setCallback(packet -> process(packet));
|
||||
this.data = new FrontendData();
|
||||
}
|
||||
|
||||
public void setAddress(InetSocketAddress address) {
|
||||
communication.setAddress(address);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Assert.test(communication.start());
|
||||
threadPool.start();
|
||||
scheduledUpdater.start();
|
||||
scheduledUpdater.executeWithFixedDelay(5000, 5000, () -> requestCompleteLoad());
|
||||
scheduledUpdater.executeWithFixedDelay(1000, 1000, () -> requestLatestUpdates());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Log.i("Disconnecting...");
|
||||
Assert.test(communication.stop());
|
||||
threadPool.stop();
|
||||
scheduledUpdater.stop();
|
||||
}
|
||||
|
||||
public FrontendCommunication getCommunication() {
|
||||
return communication;
|
||||
}
|
||||
|
||||
public SharedData getData() {
|
||||
public FrontendData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void connect(InetSocketAddress address) {
|
||||
communication.connect(address);
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
communication.disconnect();
|
||||
}
|
||||
|
||||
public void send(RequestPacket p, ResponseCallback callback) {
|
||||
send(p);
|
||||
public void send(Packet p, ResponseCallback callback) {
|
||||
threadPool.execute(() -> {
|
||||
Packet response = communication.send(p);
|
||||
Log.d("sendAwaitResponse response=%s callback?=%b", response, callback != null);
|
||||
if (response != null)
|
||||
process(response);
|
||||
if (response != null && callback != null)
|
||||
callback.onPacket(response);
|
||||
});
|
||||
}
|
||||
|
||||
public void send(Packet p) {
|
||||
communication.send(p);
|
||||
send(p, null);
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return communication.isConnected();
|
||||
public void loadServerDetailed(String serverId, ResponseCallback callback) {
|
||||
send(new RequestServerDetailedPacket(serverId), callback);
|
||||
}
|
||||
|
||||
public void loadBuildDetailed(long buildId, ResponseCallback callback) {
|
||||
send(new RequestBuildDetailedPacket(buildId), callback);
|
||||
}
|
||||
|
||||
public void loadDeploymentDetailed(long deploymentId, ResponseCallback callback) {
|
||||
send(new RequestDeploymentDetailedPacket(deploymentId), callback);
|
||||
}
|
||||
|
||||
public void loadBuildHistory(String serverId, ResponseCallback callback) {
|
||||
@@ -97,15 +133,112 @@ public class Frontend {
|
||||
|
||||
public void requestCompleteLoad() {
|
||||
send(new RequestServerListPacket(), (response) -> {
|
||||
for (SharedServerData server : data.getServers()) {
|
||||
loadBuildHistory(server.getName(), null);
|
||||
loadDeploymentHistory(server.getName(), null);
|
||||
for (SharedServerData server : ((ResponseServerListPacket) response).getServerList()) {
|
||||
loadBuildHistory(server.getName(), buildResponse -> {
|
||||
SharedBuildData lastBuild = data.getServer(server.getName()).getLastBuild();
|
||||
if (lastBuild != null)
|
||||
loadBuildDetailed(lastBuild.getId(), null);
|
||||
});
|
||||
loadDeploymentHistory(server.getName(), deployResponse -> {
|
||||
SharedDeploymentData lastDeployment = data.getServer(server.getName()).getLastDeployment();
|
||||
if (lastDeployment != null)
|
||||
loadDeploymentDetailed(lastDeployment.getId(), null);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface ResponseCallback {
|
||||
void onResponse(ResponsePacket p);
|
||||
public void requestLatestUpdates() {
|
||||
SharedServerData server = data.getSelectedServer();
|
||||
if (server == null)
|
||||
return;
|
||||
SharedDeploymentData lastDeployment = data.getServer(server.getName()).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)
|
||||
processServerDetailed((ResponseServerDetailedPacket) packet);
|
||||
else if (packet instanceof ResponseBuildListPacket)
|
||||
processBuildList((ResponseBuildListPacket) packet);
|
||||
else if (packet instanceof ResponseBuildDetailedPacket)
|
||||
processBuildDetailed((ResponseBuildDetailedPacket) packet);
|
||||
else if (packet instanceof ResponseDeploymentListPacket)
|
||||
processDeploymentList((ResponseDeploymentListPacket) packet);
|
||||
else if (packet instanceof ResponseDeploymentDetailedPacket)
|
||||
processDeploymentDetailed((ResponseDeploymentDetailedPacket) packet);
|
||||
}
|
||||
|
||||
private void processServerList(ResponseServerListPacket list) {
|
||||
List<SharedServerData> current = data.getServers();
|
||||
for (SharedServerData server : list.getServerList()) {
|
||||
if (!current.contains(server)) {
|
||||
loadServerDetailed(server.getName(), null);
|
||||
data.addServer(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processServerDetailed(ResponseServerDetailedPacket detailed) {
|
||||
SharedServerData server = detailed.getServer();
|
||||
SharedServerData existing = data.getServer(server.getName());
|
||||
if (existing != null) {
|
||||
existing.setDirectory(detailed.getDirectory());
|
||||
existing.setJvmArguments(detailed.getJvmArguments());
|
||||
} else {
|
||||
data.addServer(server);
|
||||
}
|
||||
}
|
||||
|
||||
private void processBuildList(ResponseBuildListPacket list) {
|
||||
SharedServerData server = data.getServer(list.getServerId());
|
||||
for (SharedBuildData build : list.getBuildList()) {
|
||||
if (server.getBuildData(build.getId()) == null) {
|
||||
server.addBuild(build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processBuildDetailed(ResponseBuildDetailedPacket detailed) {
|
||||
SharedServerData server = data.getServer(detailed.getServerId());
|
||||
SharedBuildData build = server.getBuildData(detailed.getBuildId());
|
||||
if (build != null) {
|
||||
build.setTime(detailed.getTime());
|
||||
build.setBuildString(detailed.getBuildString());
|
||||
build.setTestString(detailed.getTestString());
|
||||
build.setCompileTime(detailed.getCompileTime());
|
||||
build.setBuildSuccess(detailed.isBuildSuccess());
|
||||
build.setTestSuccess(detailed.isTestSuccess());
|
||||
build.setCancelled(detailed.isCancelled());
|
||||
build.setTestDetails(new TestDetails(detailed.getTestTotal(), detailed.getTestFailures()));
|
||||
} else {
|
||||
server.addBuild(detailed.getBuildData());
|
||||
}
|
||||
}
|
||||
|
||||
private void processDeploymentList(ResponseDeploymentListPacket list) {
|
||||
SharedServerData server = data.getServer(list.getServerId());
|
||||
for (SharedDeploymentData deployment : list.getDeploymentList()) {
|
||||
if (server.getDeploymentData(deployment.getId()) == null) {
|
||||
server.addDeployment(deployment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processDeploymentDetailed(ResponseDeploymentDetailedPacket detailed) {
|
||||
SharedServerData server = data.getServer(detailed.getServerId());
|
||||
SharedDeploymentData deployment = server.getDeploymentData(detailed.getDeploymentId());
|
||||
if (deployment != null) {
|
||||
deployment.setStartTime(detailed.getStartTime());
|
||||
deployment.setEndTime(detailed.getEndTime());
|
||||
deployment.setOutput(detailed.getOutput());
|
||||
} else {
|
||||
server.addDeployment(detailed.getDeploymentData());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,74 +27,58 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.lightspeed_frontend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import com.projectswg.common.callback.CallbackManager;
|
||||
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;
|
||||
|
||||
public class FrontendData {
|
||||
|
||||
private final CallbackManager<FrontendDataUpdateCallback> updateCallbackManager;
|
||||
private final CallbackManager<FrontendConnectionCallback> connectionCallbackManager;
|
||||
private List<SharedServerData> servers;
|
||||
private AtomicBoolean connected;
|
||||
private final ObservableList<SharedServerData> servers;
|
||||
private final PSWGObjectProperty<SharedServerData> selectedServer;
|
||||
private final PSWGObjectProperty<SharedBuildData> selectedBuild;
|
||||
private final PSWGObjectProperty<SharedDeploymentData> selectedDeployment;
|
||||
|
||||
public FrontendData() {
|
||||
updateCallbackManager = new CallbackManager<>("frontend-data-update", 1);
|
||||
connectionCallbackManager = new CallbackManager<>("frontend-data-connection", 1);
|
||||
servers = new ArrayList<>();
|
||||
connected = new AtomicBoolean(false);
|
||||
updateCallbackManager.start();
|
||||
connectionCallbackManager.start();
|
||||
servers = FXCollections.observableArrayList();
|
||||
selectedServer = new PSWGObjectProperty<>(null);
|
||||
selectedBuild = new PSWGObjectProperty<>(null);
|
||||
selectedDeployment = new PSWGObjectProperty<>(null);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
updateCallbackManager.stop();
|
||||
connectionCallbackManager.stop();
|
||||
|
||||
}
|
||||
|
||||
public void addDataUpdateCallback(FrontendDataUpdateCallback callback) {
|
||||
updateCallbackManager.addCallback(callback);
|
||||
public SharedServerData getSelectedServer() {
|
||||
return selectedServer.get();
|
||||
}
|
||||
|
||||
public void removeDataUpdateCallback(FrontendDataUpdateCallback callback) {
|
||||
updateCallbackManager.removeCallback(callback);
|
||||
public SharedBuildData getSelectedBuild() {
|
||||
return selectedBuild.get();
|
||||
}
|
||||
|
||||
public void addConnectionCallback(FrontendConnectionCallback callback) {
|
||||
connectionCallbackManager.addCallback(callback);
|
||||
public SharedDeploymentData getSelectedDeployment() {
|
||||
return selectedDeployment.get();
|
||||
}
|
||||
|
||||
public void removeConnectionCallback(FrontendConnectionCallback callback) {
|
||||
connectionCallbackManager.removeCallback(callback);
|
||||
public PSWGObjectProperty<SharedServerData> getSelectedServerProperty() {
|
||||
return selectedServer;
|
||||
}
|
||||
|
||||
public void setServers(List<String> servers) {
|
||||
synchronized (this.servers) {
|
||||
for (SharedServerData server : new ArrayList<>(this.servers)) {
|
||||
if (!servers.contains(server.getName())) {
|
||||
this.servers.remove(server);
|
||||
} else {
|
||||
servers.remove(server.getName());
|
||||
}
|
||||
}
|
||||
for (String server : servers) {
|
||||
this.servers.add(new SharedServerData(server));
|
||||
}
|
||||
}
|
||||
notifyDataUpdated(FrontendDataType.SERVER_LIST);
|
||||
public PSWGObjectProperty<SharedBuildData> getSelectedBuildProperty() {
|
||||
return selectedBuild;
|
||||
}
|
||||
|
||||
public void setConnectionStatus(boolean connected) {
|
||||
if (this.connected.getAndSet(connected) != connected)
|
||||
notifyConnectionUpdated(connected);
|
||||
public PSWGObjectProperty<SharedDeploymentData> getSelectedDeploymentProperty() {
|
||||
return selectedDeployment;
|
||||
}
|
||||
|
||||
public List<SharedServerData> getServers() {
|
||||
return Collections.unmodifiableList(servers);
|
||||
public ObservableList<SharedServerData> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public SharedServerData getServer(String serverId) {
|
||||
@@ -107,28 +91,44 @@ public class FrontendData {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected.get();
|
||||
public SharedBuildData getBuild(long buildId) {
|
||||
synchronized (servers) {
|
||||
for (SharedServerData server : servers) {
|
||||
SharedBuildData build = server.getBuildData(buildId);
|
||||
if (build != null)
|
||||
return build;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void notifyDataUpdated(FrontendDataType dataType) {
|
||||
updateCallbackManager.callOnEach((callback) -> callback.onDataUpdated(dataType));
|
||||
public SharedDeploymentData getDeployment(long deploymentId) {
|
||||
synchronized (servers) {
|
||||
for (SharedServerData server : servers) {
|
||||
SharedDeploymentData deployment = server.getDeploymentData(deploymentId);
|
||||
if (deployment != null)
|
||||
return deployment;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void notifyConnectionUpdated(boolean newState) {
|
||||
connectionCallbackManager.callOnEach((callback) -> callback.onConnectionChanged(newState));
|
||||
public void setSelectedServer(SharedServerData server) {
|
||||
this.selectedServer.set(server);
|
||||
}
|
||||
|
||||
public interface FrontendDataUpdateCallback {
|
||||
void onDataUpdated(FrontendDataType dataType);
|
||||
public void setSelectedBuild(SharedBuildData build) {
|
||||
this.selectedBuild.set(build);
|
||||
}
|
||||
|
||||
public interface FrontendConnectionCallback {
|
||||
void onConnectionChanged(boolean connected);
|
||||
public void setSelectedDeployment(SharedDeploymentData deployment) {
|
||||
this.selectedDeployment.set(deployment);
|
||||
}
|
||||
|
||||
public enum FrontendDataType {
|
||||
SERVER_LIST
|
||||
public void addServer(SharedServerData server) {
|
||||
synchronized (servers) {
|
||||
servers.add(server);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,43 +30,54 @@ package com.projectswg.lightspeed_frontend;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import com.projectswg.common.control.IntentManager;
|
||||
import com.projectswg.common.info.Log;
|
||||
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.javafx.FXMLUtilities;
|
||||
import com.projectswg.common.javafx.ResourceUtilities;
|
||||
import com.projectswg.lightspeed_frontend.gui.LightspeedPrimaryView;
|
||||
import com.projectswg.lightspeed_frontend.intents.ConnectionStateUpdateIntent;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
public class LightspeedFrontendGUI extends Application {
|
||||
|
||||
public static final Frontend FRONTEND = new Frontend();
|
||||
public static final FrontendData DATA = FRONTEND.getData();
|
||||
|
||||
private final Frontend frontend;
|
||||
private final LightspeedPrimaryView primaryView;
|
||||
|
||||
private LightspeedPrimaryView primaryView;
|
||||
|
||||
public LightspeedFrontendGUI() {
|
||||
frontend = new Frontend();
|
||||
primaryView = new LightspeedPrimaryView(frontend);
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.class, i -> onConnectionUpdate(((ConnectionStateUpdateIntent) i).isConnected()));
|
||||
frontend = LightspeedFrontendGUI.FRONTEND;
|
||||
primaryView = null;
|
||||
frontend.start();
|
||||
}
|
||||
|
||||
public static void main(String [] args) {
|
||||
ResourceUtilities.setPrimarySource(LightspeedFrontendGUI.class);
|
||||
Log.addWrapper(new ConsoleLogWrapper(LogLevel.VERBOSE));
|
||||
launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
processConnect();
|
||||
IntentManager.getInstance().initialize();
|
||||
Scene scene = new Scene(primaryView, 800, 640);
|
||||
primaryView = (LightspeedPrimaryView) FXMLUtilities.loadFxml("PrimaryView.fxml", Locale.ENGLISH);
|
||||
processConnect();
|
||||
Parent root = primaryView.getRoot();
|
||||
primaryStage.setTitle("Lightspeed Frontend");
|
||||
primaryStage.setScene(scene);
|
||||
primaryView.setOnMouseClicked((event) -> primaryView.requestFocus());
|
||||
primaryView.requestFocus();
|
||||
primaryStage.setScene(new Scene(root));
|
||||
root.setOnMouseClicked((event) -> root.requestFocus());
|
||||
root.requestFocus();
|
||||
primaryStage.show();
|
||||
primaryStage.setOnCloseRequest((we) -> {
|
||||
close(we);
|
||||
@@ -88,9 +99,8 @@ public class LightspeedFrontendGUI extends Application {
|
||||
}
|
||||
}
|
||||
try {
|
||||
InetSocketAddress sock = new InetSocketAddress(InetAddress.getByName(address), port);
|
||||
frontend.connect(sock);
|
||||
primaryView.setConnectAddress(sock);
|
||||
primaryView.setConnectAddress(new InetSocketAddress(InetAddress.getByName(address), port));
|
||||
frontend.requestCompleteLoad();
|
||||
} catch (UnknownHostException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
@@ -98,16 +108,11 @@ public class LightspeedFrontendGUI extends Application {
|
||||
|
||||
private void close(WindowEvent we) {
|
||||
Log.i("Closing GUI...");
|
||||
primaryView.close();
|
||||
FXMLUtilities.terminate();
|
||||
frontend.stop();
|
||||
Log.i("Terminating IntentManager...");
|
||||
IntentManager.getInstance().terminate();
|
||||
Log.i("Closed.");
|
||||
}
|
||||
|
||||
private void onConnectionUpdate(boolean connected) {
|
||||
if (connected)
|
||||
frontend.requestCompleteLoad();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
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.PostBuildPacket;
|
||||
import com.projectswg.common.network.packets.post.PostCreateServerPacket;
|
||||
@@ -70,8 +72,15 @@ public class LightspeedFrontendText {
|
||||
communication = new FrontendCommunication();
|
||||
inbound = new ArrayDeque<>();
|
||||
running = false;
|
||||
communication.setAddress(new InetSocketAddress(InetAddress.getLoopbackAddress(), 44444));
|
||||
communication.setCallback(packet -> {
|
||||
synchronized (inbound) {
|
||||
inbound.add(packet);
|
||||
inbound.notify();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
running = true;
|
||||
communication.start();
|
||||
@@ -95,11 +104,8 @@ public class LightspeedFrontendText {
|
||||
case "quit":
|
||||
processQuit();
|
||||
break;
|
||||
case "connect":
|
||||
processConnect(args);
|
||||
break;
|
||||
case "disconnect":
|
||||
processDisconnect();
|
||||
case "setup":
|
||||
processSetup(args);
|
||||
break;
|
||||
case "request":
|
||||
processRequest(args);
|
||||
@@ -114,7 +120,7 @@ public class LightspeedFrontendText {
|
||||
running = false;
|
||||
}
|
||||
|
||||
private void processConnect(String [] args) {
|
||||
private void processSetup(String [] args) {
|
||||
InetAddress addr = InetAddress.getLoopbackAddress();
|
||||
int port = 44444;
|
||||
try {
|
||||
@@ -129,18 +135,7 @@ public class LightspeedFrontendText {
|
||||
Log.e("Invalid call to connect! Invalid port: " + args[2]);
|
||||
return;
|
||||
}
|
||||
communication.connect(new InetSocketAddress(addr, port));
|
||||
try {
|
||||
while (!communication.isConnected()) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Log.w(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void processDisconnect() {
|
||||
communication.disconnect();
|
||||
communication.setAddress(new InetSocketAddress(addr, port));
|
||||
}
|
||||
|
||||
private void processRequest(String [] args) {
|
||||
@@ -320,6 +315,7 @@ public class LightspeedFrontendText {
|
||||
}
|
||||
|
||||
public static void main(String [] args) {
|
||||
Log.addWrapper(new ConsoleLogWrapper(LogLevel.VERBOSE));
|
||||
LightspeedFrontendText frontend = new LightspeedFrontendText();
|
||||
frontend.run();
|
||||
}
|
||||
|
||||
@@ -28,22 +28,29 @@
|
||||
package com.projectswg.lightspeed_frontend.communication;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.debug.Assert;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.utilities.ThreadUtilities;
|
||||
|
||||
public class FrontendCommunication {
|
||||
|
||||
private final AtomicBoolean running;
|
||||
|
||||
private ExecutorService executor;
|
||||
private ResponseCallback callback;
|
||||
private InetSocketAddress address;
|
||||
|
||||
public FrontendCommunication() {
|
||||
running = new AtomicBoolean(false);
|
||||
callback = null;
|
||||
address = null;
|
||||
}
|
||||
|
||||
public void setCallback(ResponseCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void setAddress(InetSocketAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
@@ -51,7 +58,6 @@ public class FrontendCommunication {
|
||||
Assert.fail();
|
||||
return false;
|
||||
}
|
||||
executor = Executors.newSingleThreadExecutor(ThreadUtilities.newThreadFactory("frontend-communication"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,25 +66,18 @@ public class FrontendCommunication {
|
||||
Assert.fail();
|
||||
return false;
|
||||
}
|
||||
executor.shutdownNow();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return false;
|
||||
public Packet send(Packet packet) {
|
||||
Packet response = HttpClient.requestPacket(address, packet);
|
||||
if (response != null && callback != null)
|
||||
callback.onPacket(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
public void connect(InetSocketAddress addr) {
|
||||
if (addr == null)
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
|
||||
}
|
||||
|
||||
public void send(Packet p) {
|
||||
|
||||
public interface ResponseCallback {
|
||||
void onPacket(Packet packet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+54
-78
@@ -25,100 +25,76 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.network.protocol;
|
||||
package com.projectswg.lightspeed_frontend.communication;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.joshlarson.json.JSON;
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
import com.projectswg.common.network.NetBufferStream;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.common.network.packets.post.PostPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestPacket;
|
||||
|
||||
public class AlphaProtocol extends Protocol {
|
||||
public class HttpClient {
|
||||
|
||||
public static final String VERSION = "alpha";
|
||||
|
||||
private final NetBufferStream stream;
|
||||
private final Queue<Packet> incoming;
|
||||
|
||||
protected AlphaProtocol() {
|
||||
super(VERSION);
|
||||
stream = new NetBufferStream(4096);
|
||||
incoming = new ArrayDeque<>();
|
||||
public static Packet requestPacket(InetSocketAddress address, Packet packet) {
|
||||
try {
|
||||
String str = requestString(address, packet);
|
||||
JSONObject obj = JSON.readObject(str, true);
|
||||
PacketType type = PacketType.valueOf(obj.getString("type"));
|
||||
return Packet.inflate(obj, type);
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer preparePacket(Packet p) {
|
||||
String json = p.getJSON().toString();
|
||||
NetBuffer buf = NetBuffer.allocate(4+json.length()*2);
|
||||
buf.addUnicode(json);
|
||||
buf.getBuffer().flip();
|
||||
return buf.getBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIncomingData(byte [] data) {
|
||||
synchronized (stream) {
|
||||
try {
|
||||
stream.write(data);
|
||||
while (stream.remaining() >= 4) {
|
||||
stream.mark();
|
||||
int length = stream.getInt();
|
||||
stream.rewind();
|
||||
if (stream.remaining() < length * 2 + 4)
|
||||
return;
|
||||
String jsonRaw = stream.getUnicode();
|
||||
JSONObject json = JSON.readObject(jsonRaw, true);
|
||||
if (json != null)
|
||||
processPacket(json);
|
||||
else
|
||||
Log.d("Unknown JSON string:%n%s", jsonRaw);
|
||||
}
|
||||
stream.compact();
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
public static String requestString(InetSocketAddress address, Packet packet) throws IOException {
|
||||
URL url = new URL(generateURL(address, packet));
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
|
||||
con.setRequestMethod((packet instanceof PostPacket) ? "POST" : "GET");
|
||||
con.setRequestProperty("User-Agent", "LightspeedFrontend");
|
||||
|
||||
int responseCode = con.getResponseCode();
|
||||
if (responseCode != 200)
|
||||
return "";
|
||||
|
||||
StringBuilder response = new StringBuilder("");
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
|
||||
String inputLine;
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
}
|
||||
return response.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet getNextPacket() {
|
||||
synchronized (incoming) {
|
||||
return incoming.poll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPacketCount() {
|
||||
synchronized (incoming) {
|
||||
return incoming.size();
|
||||
}
|
||||
}
|
||||
|
||||
private void processPacket(JSONObject json) {
|
||||
if (!json.containsKey("type")) {
|
||||
Log.e("Received invalid packet without type!");
|
||||
return;
|
||||
}
|
||||
PacketType type = null;
|
||||
try {
|
||||
type = PacketType.valueOf(json.getString("type"));
|
||||
} catch (IllegalArgumentException | NullPointerException e) {
|
||||
Log.e("Received unknown packet! Type: " + json.getString("type"));
|
||||
return;
|
||||
}
|
||||
Packet p = Packet.inflate(json, type);
|
||||
if (p == null)
|
||||
return;
|
||||
synchronized (incoming) {
|
||||
incoming.add(p);
|
||||
private static String generateURL(InetSocketAddress address, Packet packet) throws UnsupportedEncodingException {
|
||||
StringBuilder url = new StringBuilder("http://"+address.getAddress().getHostAddress()+":"+address.getPort()+"/?");
|
||||
JSONObject obj = packet.getJSON();
|
||||
if (packet instanceof PostPacket)
|
||||
url.append("type=" + ((PostPacket) packet).getType().name().replace("POST_", "") + '&');
|
||||
else if (packet instanceof RequestPacket)
|
||||
url.append("type=" + ((RequestPacket) packet).getType().name().replace("REQUEST_", "") + '&');
|
||||
else
|
||||
return url.toString();
|
||||
obj.remove("type");
|
||||
for (Entry<String, Object> entry : obj.entrySet()) {
|
||||
url.append(entry.getKey() + '=' + URLEncoder.encode(entry.getValue().toString(), "ASCII") + '&');
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,8 @@ import javafx.scene.text.FontWeight;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
|
||||
|
||||
public class InternalWindow extends Region {
|
||||
|
||||
|
||||
@@ -29,46 +29,32 @@ package com.projectswg.lightspeed_frontend.gui;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.IntentManager;
|
||||
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
|
||||
import com.projectswg.common.javafx.FXMLController;
|
||||
import com.projectswg.common.javafx.FXMLUtilities;
|
||||
import com.projectswg.common.network.packets.post.PostBuildPacket;
|
||||
import com.projectswg.common.utilities.ThreadUtilities;
|
||||
import com.projectswg.common.network.packets.post.PostDeployPacket;
|
||||
import com.projectswg.common.network.packets.post.PostStopDeployPacket;
|
||||
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.SharedDeploymentData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
import com.projectswg.lightspeed_frontend.gui.primary_tabs.BuildTab;
|
||||
import com.projectswg.lightspeed_frontend.gui.primary_tabs.DeploymentTab;
|
||||
import com.projectswg.lightspeed_frontend.gui.primary_tabs.GeneralTab;
|
||||
import com.projectswg.lightspeed_frontend.intents.ConnectionStateUpdateIntent;
|
||||
import com.projectswg.lightspeed_frontend.javafx.FrontendFXMLLoader;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class LightspeedPrimaryView extends VBox implements Initializable {
|
||||
|
||||
private final ExecutorService executor;
|
||||
private final Frontend frontend;
|
||||
private final AtomicBoolean initialized;
|
||||
public class LightspeedPrimaryView implements FXMLController {
|
||||
|
||||
@FXML
|
||||
private GeneralTab generalTab;
|
||||
@FXML
|
||||
private BuildTab buildTab;
|
||||
@FXML
|
||||
private DeploymentTab deploymentTab;
|
||||
private VBox primaryViewContainer;
|
||||
@FXML
|
||||
private MenuButton commonServerStatus;
|
||||
@FXML
|
||||
@@ -76,93 +62,82 @@ public class LightspeedPrimaryView extends VBox implements Initializable {
|
||||
@FXML
|
||||
private MenuButton commonDeploymentStatus;
|
||||
|
||||
private SharedServerData server;
|
||||
private InetSocketAddress address;
|
||||
private final PswgBasicScheduledThread scheduledUpdater;
|
||||
private final Frontend frontend;
|
||||
|
||||
public LightspeedPrimaryView(Frontend frontend) {
|
||||
if (frontend == null)
|
||||
throw new NullPointerException("Frontend cannot be null");
|
||||
this.executor = Executors.newSingleThreadExecutor(ThreadUtilities.newThreadFactory("lightspeed-tab"));
|
||||
this.frontend = frontend;
|
||||
this.initialized = new AtomicBoolean(false);
|
||||
this.server = null;
|
||||
this.address = null;
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.class, i -> update());
|
||||
FrontendFXMLLoader.load(this, "fxml/PrimaryView.fxml");
|
||||
public LightspeedPrimaryView() {
|
||||
this.scheduledUpdater = new PswgBasicScheduledThread("primary-view-updater", () -> updateUi());
|
||||
this.frontend = LightspeedFrontendGUI.FRONTEND;
|
||||
}
|
||||
|
||||
public void setConnectAddress(InetSocketAddress address) {
|
||||
this.address = address;
|
||||
frontend.setAddress(address);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Assert.test(!executor.isShutdown());
|
||||
executor.shutdownNow();
|
||||
@Override
|
||||
public Parent getRoot() {
|
||||
return primaryViewContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
initialized.set(true);
|
||||
update();
|
||||
generalTab.setFrontend(frontend);
|
||||
buildTab.setFrontend(frontend);
|
||||
deploymentTab.setFrontend(frontend);
|
||||
generalTab.setSelectedServerChangedCallback((server) -> {
|
||||
this.server = server;
|
||||
buildTab.setServer(server);
|
||||
deploymentTab.setServer(server);
|
||||
update();
|
||||
});
|
||||
buildTab.setSelectedBuildChangedCallback((build) -> {
|
||||
deploymentTab.setBuild(build);
|
||||
});
|
||||
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);
|
||||
frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> updateUi());
|
||||
updateUi();
|
||||
scheduledUpdater.startWithFixedRate(1000, 1000);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
@Override
|
||||
public void terminate() {
|
||||
scheduledUpdater.stop();
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
Platform.runLater(() -> {
|
||||
setServerStatusText(frontend.isConnected());
|
||||
setBuildStatusText(server == null ? null : server.getLastBuild());
|
||||
setDeploymentStatusText(server == null ? null : server.getLastDeployment());
|
||||
setBuildStatusText();
|
||||
setDeploymentStatusText();
|
||||
});
|
||||
}
|
||||
|
||||
private void setServerStatusText(boolean connected) {
|
||||
commonServerStatus.setText(String.format("Server: %s", connected ? "Connected" : "Disconnected"));
|
||||
if (connected) {
|
||||
MenuItem disconnect = new MenuItem("Disconnect");
|
||||
disconnect.setOnAction((event) -> frontend.disconnect());
|
||||
commonServerStatus.getItems().setAll(disconnect);
|
||||
} else {
|
||||
if (address != null) {
|
||||
MenuItem connect = new MenuItem("Connect");
|
||||
connect.setOnAction((event) -> frontend.connect(address));
|
||||
commonServerStatus.getItems().setAll(connect);
|
||||
} else {
|
||||
commonServerStatus.getItems().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBuildStatusText(SharedBuildData build) {
|
||||
List<MenuItem> items = new ArrayList<>();
|
||||
private void setBuildStatusText() {
|
||||
SharedServerData server = frontend.getData().getSelectedServer();
|
||||
SharedBuildData build = server == null ? null : server.getLastBuild();
|
||||
if (build != null) {
|
||||
commonBuildStatus.setText(String.format("Build: %s", (build.isBuildSuccess() && build.isTestSuccess()) ? "Success" : "Failure"));
|
||||
} else {
|
||||
commonBuildStatus.setText("Build: N/A");
|
||||
}
|
||||
if (frontend.isConnected() && server != null) {
|
||||
if (server != null && commonBuildStatus.getItems().isEmpty()) {
|
||||
MenuItem startBuild = new MenuItem("Start Build");
|
||||
startBuild.setOnAction((event) -> frontend.send(new PostBuildPacket(server.getName())));
|
||||
items.add(startBuild);
|
||||
commonBuildStatus.getItems().setAll(startBuild);
|
||||
} else {
|
||||
if (server == null)
|
||||
commonBuildStatus.getItems().clear();
|
||||
}
|
||||
commonBuildStatus.getItems().setAll(items);
|
||||
}
|
||||
|
||||
private void setDeploymentStatusText(SharedDeploymentData deployment) {
|
||||
String str = "N/A";
|
||||
if (deployment != null)
|
||||
str = deployment.getEndTime() == -1 ? "Running" : "Stopped";
|
||||
commonDeploymentStatus.setText(String.format("Deployment: %s", str));
|
||||
private void setDeploymentStatusText() {
|
||||
SharedServerData server = frontend.getData().getSelectedServer();
|
||||
SharedDeploymentData deployment = server == null ? null : server.getLastDeployment();
|
||||
if (deployment != null) {
|
||||
commonDeploymentStatus.setText("Deployment: " + (deployment.getEndTime() == 0 ? "Running" : "Stopped"));
|
||||
} else {
|
||||
commonDeploymentStatus.setText("Deployment: N/A");
|
||||
}
|
||||
if (server != null && commonDeploymentStatus.getItems().isEmpty()) {
|
||||
MenuItem startDeploy = new MenuItem("Start Deployment");
|
||||
MenuItem stopDeploy = new MenuItem("Stop Deployment");
|
||||
startDeploy.setOnAction((event) -> frontend.send(new PostDeployPacket(server.getName())));
|
||||
stopDeploy.setOnAction((event) -> frontend.send(new PostStopDeployPacket(server.getName())));
|
||||
commonDeploymentStatus.getItems().setAll(startDeploy, stopDeploy);
|
||||
} else {
|
||||
if (server == null)
|
||||
commonDeploymentStatus.getItems().clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,30 +28,34 @@
|
||||
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
|
||||
import com.projectswg.common.data.TestDetails;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.javafx.FXMLController;
|
||||
import com.projectswg.common.javafx.FXMLUtilities;
|
||||
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.javafx.FrontendFXMLLoader;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
public class BuildTab extends GridPane implements Initializable {
|
||||
public class BuildTab implements FXMLController {
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> buildComboBox;
|
||||
private Parent rootBuild;
|
||||
@FXML
|
||||
private ComboBox<SharedBuildData> buildComboBox;
|
||||
@FXML
|
||||
private Label serverNameText;
|
||||
@FXML
|
||||
@@ -67,35 +71,22 @@ public class BuildTab extends GridPane implements Initializable {
|
||||
@FXML
|
||||
private Label testText;
|
||||
|
||||
private SelectedBuildChangedCallback callback;
|
||||
private SharedServerData selectedServerData;
|
||||
private SharedBuildData selectedBuildData;
|
||||
private final PswgBasicScheduledThread scheduledUpdater;
|
||||
private final Frontend frontend;
|
||||
|
||||
public BuildTab() {
|
||||
callback = null;
|
||||
selectedServerData = null;
|
||||
selectedBuildData = null;
|
||||
FrontendFXMLLoader.load(this, "fxml/primary_tabs/Build.fxml");
|
||||
this.scheduledUpdater = new PswgBasicScheduledThread("build-tab-updater", () -> requestUpdate());
|
||||
this.frontend = LightspeedFrontendGUI.FRONTEND;
|
||||
}
|
||||
|
||||
public void setFrontend(Frontend frontend) {
|
||||
|
||||
}
|
||||
|
||||
public void setSelectedBuildChangedCallback(SelectedBuildChangedCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void setServer(SharedServerData server) {
|
||||
if (this.selectedServerData == server)
|
||||
return;
|
||||
this.selectedServerData = server;
|
||||
this.selectedBuildData = null;
|
||||
updateBuildList();
|
||||
@Override
|
||||
public Parent getRoot() {
|
||||
return rootBuild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
FXMLUtilities.onFxmlLoaded(this);
|
||||
serverNameText.getStyleClass().setAll("white-label");
|
||||
buildIdText.getStyleClass().setAll("white-label");
|
||||
statusText.getStyleClass().setAll("white-label");
|
||||
@@ -103,101 +94,117 @@ public class BuildTab extends GridPane implements Initializable {
|
||||
compileTimeText.getStyleClass().setAll("white-label");
|
||||
modeText.getStyleClass().setAll("white-label");
|
||||
testText.getStyleClass().setAll("white-label");
|
||||
buildComboBox.selectionModelProperty().addListener((v, prev, next) -> {
|
||||
if (selectedServerData == null)
|
||||
return;
|
||||
for (SharedBuildData build : selectedServerData.getBuilds()) {
|
||||
String val = v.getValue().getSelectedItem();
|
||||
if (!val.isEmpty() && build.getId() == Long.parseLong(val)) {
|
||||
selectBuild(build);
|
||||
return;
|
||||
}
|
||||
}
|
||||
selectBuild(null);
|
||||
buildComboBox.setConverter(new StringConverter<SharedBuildData>() {
|
||||
public String toString(SharedBuildData server) { return Long.toString(server.getId()); }
|
||||
public SharedBuildData fromString(String string) { return frontend.getData().getBuild(Long.parseLong(string)); }
|
||||
});
|
||||
buildComboBox.getSelectionModel().selectedItemProperty().addListener((val, prev, next) -> {
|
||||
Log.d("selected build manually '%s'", next);
|
||||
frontend.getData().setSelectedBuild(next);
|
||||
if (next != null)
|
||||
frontend.loadBuildDetailed(next.getId(), response -> Platform.runLater(() -> updateBuildDetails()));
|
||||
updateBuildDetails();
|
||||
});
|
||||
this.frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> updateUi());
|
||||
updateUi();
|
||||
scheduledUpdater.startWithFixedRate(10000, 10000);
|
||||
}
|
||||
|
||||
private void selectBuild(SharedBuildData build) {
|
||||
Log.d("Selected: %s", build);
|
||||
if (build != null)
|
||||
buildComboBox.getSelectionModel().select(Long.toString(build.getId()));
|
||||
else
|
||||
buildComboBox.getSelectionModel().selectFirst();
|
||||
selectedBuildData = build;
|
||||
if (callback != null)
|
||||
callback.onBuildChanged(build);
|
||||
updateUi();
|
||||
@Override
|
||||
public void terminate() {
|
||||
scheduledUpdater.stop();
|
||||
}
|
||||
|
||||
private void requestUpdate() {
|
||||
SharedBuildData selected = frontend.getData().getSelectedBuild();
|
||||
if (selected != null) {
|
||||
frontend.loadBuildDetailed(selected.getId(), response -> updateUi());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
Platform.runLater(() -> {
|
||||
setServerName();
|
||||
setBuildId();
|
||||
setStatus();
|
||||
setTime();
|
||||
setCompileTime();
|
||||
setMode();
|
||||
setTests();
|
||||
updateBuildList();
|
||||
updateBuildDetails();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBuildList() {
|
||||
List<SharedBuildData> buildList = selectedServerData.getBuilds();
|
||||
String [] builds = new String[buildList.size()];
|
||||
Arrays.sort(builds, (a, b) -> b.compareTo(a));
|
||||
for (int i = 0; i < buildList.size(); i++) {
|
||||
builds[i] = Long.toString(buildList.get(i).getId());
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
buildComboBox.setItems(FXCollections.observableArrayList(builds));
|
||||
buildComboBox.getItems().add(0, "");
|
||||
if (selectedBuildData != null) {
|
||||
selectBuild(selectedBuildData);
|
||||
SharedServerData selectedServer = frontend.getData().getSelectedServer();
|
||||
if (selectedServer != null) {
|
||||
List<SharedBuildData> updated = selectedServer.getBuilds();
|
||||
List<SharedBuildData> original = buildComboBox.getItems();
|
||||
for (SharedBuildData u : updated) {
|
||||
if (!original.contains(u))
|
||||
original.add(u);
|
||||
}
|
||||
});
|
||||
Iterator<SharedBuildData> it = original.iterator();
|
||||
while (it.hasNext()) {
|
||||
SharedBuildData o = it.next();
|
||||
if (!updated.contains(o))
|
||||
it.remove();
|
||||
}
|
||||
original.sort((a, b) -> Long.compare(b.getId(), a.getId()));
|
||||
} else {
|
||||
buildComboBox.getItems().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBuildDetails() {
|
||||
setServerName();
|
||||
setBuildId();
|
||||
setStatus();
|
||||
setTime();
|
||||
setCompileTime();
|
||||
setMode();
|
||||
setTests();
|
||||
}
|
||||
|
||||
private void setServerName() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
serverNameText.setText("N/A");
|
||||
} else {
|
||||
serverNameText.setText(selectedBuildData.getServer().getName());
|
||||
serverNameText.setText(selectedBuild.getServer().getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void setBuildId() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
buildIdText.setText("N/A");
|
||||
} else {
|
||||
buildIdText.setText(Long.toString(selectedBuildData.getId()));
|
||||
buildIdText.setText(Long.toString(selectedBuild.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setStatus() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
statusText.getStyleClass().setAll("white-label");
|
||||
statusText.setText("N/A");
|
||||
} else {
|
||||
boolean success = selectedBuildData.isBuildSuccess() && selectedBuildData.isTestSuccess();
|
||||
boolean success = selectedBuild.isBuildSuccess() && selectedBuild.isTestSuccess();
|
||||
statusText.getStyleClass().setAll(success ? "green-label" : "red-label");
|
||||
statusText.setText(success ? "Success" : "Failure");
|
||||
}
|
||||
}
|
||||
|
||||
private void setTime() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
timeText.setText("N/A");
|
||||
} else {
|
||||
timeText.setText(TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedBuildData.getTime())));
|
||||
timeText.setText(TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedBuild.getTime())));
|
||||
}
|
||||
}
|
||||
|
||||
private void setCompileTime() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
compileTimeText.setText("N/A");
|
||||
} else {
|
||||
compileTimeText.setText(getTime((long) (selectedBuildData.getCompileTime()*1E3)));
|
||||
compileTimeText.setText(getTime((long) (selectedBuild.getCompileTime()*1E3)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,10 +213,11 @@ public class BuildTab extends GridPane implements Initializable {
|
||||
}
|
||||
|
||||
private void setTests() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedBuildData selectedBuild = frontend.getData().getSelectedBuild();
|
||||
if (selectedBuild == null) {
|
||||
testText.setText("N/A");
|
||||
} else {
|
||||
TestDetails details = selectedBuildData.getTestDetails();
|
||||
TestDetails details = selectedBuild.getTestDetails();
|
||||
int total = details.getTotal();
|
||||
int passed = total-details.getFailures();
|
||||
testText.setText(String.format("%d of %d passed", passed, total));
|
||||
|
||||
@@ -28,29 +28,34 @@
|
||||
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.javafx.FXMLController;
|
||||
import com.projectswg.common.javafx.FXMLUtilities;
|
||||
import com.projectswg.common.utilities.TimeUtilities;
|
||||
import com.projectswg.lightspeed_frontend.Frontend;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
|
||||
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
import com.projectswg.lightspeed_frontend.javafx.FrontendFXMLLoader;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
public class DeploymentTab extends GridPane implements Initializable {
|
||||
public class DeploymentTab implements FXMLController {
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> deploymentComboBox;
|
||||
private Parent rootDeployment;
|
||||
@FXML
|
||||
private ComboBox<SharedDeploymentData> deploymentComboBox;
|
||||
@FXML
|
||||
private Label serverNameText;
|
||||
@FXML
|
||||
@@ -64,51 +69,86 @@ public class DeploymentTab extends GridPane implements Initializable {
|
||||
@FXML
|
||||
private Label uptimeText;
|
||||
@FXML
|
||||
private Label logText;
|
||||
private TextArea logTextArea;
|
||||
|
||||
private SharedServerData selectedServerData;
|
||||
private SharedBuildData selectedBuildData;
|
||||
private SharedDeploymentData selectedDeploymentData;
|
||||
private final PswgScheduledThreadPool scheduledUpdater;
|
||||
private final Frontend frontend;
|
||||
|
||||
public DeploymentTab() {
|
||||
FrontendFXMLLoader.load(this, "fxml/primary_tabs/Deployment.fxml");
|
||||
this.scheduledUpdater = new PswgScheduledThreadPool(1, "deployment-tab-updater");
|
||||
this.frontend = LightspeedFrontendGUI.FRONTEND;
|
||||
}
|
||||
|
||||
public void setServer(SharedServerData server) {
|
||||
if (this.selectedServerData == server)
|
||||
return;
|
||||
this.selectedServerData = server;
|
||||
this.selectedBuildData = null;
|
||||
updateDeploymentList();
|
||||
}
|
||||
|
||||
public void setBuild(SharedBuildData build) {
|
||||
if (this.selectedBuildData == build)
|
||||
return;
|
||||
if (build == null)
|
||||
this.selectedServerData = null;
|
||||
else
|
||||
this.selectedServerData = build.getServer();
|
||||
this.selectedBuildData = build;
|
||||
updateDeploymentList();
|
||||
}
|
||||
|
||||
public void setFrontend(Frontend frontend) {
|
||||
|
||||
@Override
|
||||
public Parent getRoot() {
|
||||
return rootDeployment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
FXMLUtilities.onFxmlLoaded(this);
|
||||
serverNameText.getStyleClass().setAll("white-label");
|
||||
buildIdText.getStyleClass().setAll("white-label");
|
||||
deploymentIdText.getStyleClass().setAll("white-label");
|
||||
statusText.getStyleClass().setAll("white-label");
|
||||
startTimeText.getStyleClass().setAll("white-label");
|
||||
uptimeText.getStyleClass().setAll("white-label");
|
||||
deploymentComboBox.setConverter(new DeploymentStringConverter());
|
||||
deploymentComboBox.getSelectionModel().selectedItemProperty().addListener((val, prev, next) -> {
|
||||
Log.d("selected deployment manually '%s'", next);
|
||||
frontend.getData().setSelectedDeployment(next);
|
||||
if (next != null)
|
||||
frontend.loadDeploymentDetailed(next.getId(), response -> Platform.runLater(() -> updateDeploymentDetails()));
|
||||
updateDeploymentDetails();
|
||||
});
|
||||
this.frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> updateUi());
|
||||
updateUi();
|
||||
scheduledUpdater.start();
|
||||
scheduledUpdater.executeWithFixedRate(10000, 10000, () -> requestUpdate());
|
||||
scheduledUpdater.executeWithFixedRate(1000, 1000, () -> Platform.runLater(() -> updateDeploymentDetails()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() {
|
||||
scheduledUpdater.stop();
|
||||
}
|
||||
|
||||
private void requestUpdate() {
|
||||
SharedDeploymentData selected = frontend.getData().getSelectedDeployment();
|
||||
if (selected != null) {
|
||||
frontend.loadDeploymentDetailed(selected.getId(), response -> updateUi());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
Platform.runLater(() -> {
|
||||
updateDeploymentList();
|
||||
updateDeploymentDetails();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateDeploymentList() {
|
||||
SharedServerData selectedServer = frontend.getData().getSelectedServer();
|
||||
if (selectedServer != null) {
|
||||
List<SharedDeploymentData> updated = selectedServer.getDeployments();
|
||||
List<SharedDeploymentData> original = deploymentComboBox.getItems();
|
||||
for (SharedDeploymentData u : updated) {
|
||||
if (!original.contains(u))
|
||||
original.add(u);
|
||||
}
|
||||
Iterator<SharedDeploymentData> it = original.iterator();
|
||||
while (it.hasNext()) {
|
||||
SharedDeploymentData o = it.next();
|
||||
if (!updated.contains(o))
|
||||
it.remove();
|
||||
}
|
||||
original.sort((a, b) -> Long.compare(b.getId(), a.getId()));
|
||||
} else {
|
||||
deploymentComboBox.getItems().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDeploymentDetails() {
|
||||
setServerName();
|
||||
setBuildId();
|
||||
setDeploymentId();
|
||||
@@ -118,86 +158,66 @@ public class DeploymentTab extends GridPane implements Initializable {
|
||||
setLog();
|
||||
}
|
||||
|
||||
private void selectDeployment(SharedDeploymentData deployment) {
|
||||
if (deployment != null)
|
||||
deploymentComboBox.getSelectionModel().select(Long.toString(deployment.getId()));
|
||||
else
|
||||
deploymentComboBox.getSelectionModel().selectFirst();
|
||||
selectedDeploymentData = deployment;
|
||||
updateUi();
|
||||
}
|
||||
|
||||
private void updateDeploymentList() {
|
||||
List<SharedDeploymentData> deploymentList = new ArrayList<>();
|
||||
if (selectedServerData != null) {
|
||||
deploymentList.addAll(selectedServerData.getDeployments());
|
||||
}
|
||||
String [] deployments = new String[deploymentList.size()];
|
||||
Arrays.sort(deployments, (a, b) -> b.compareTo(a));
|
||||
for (int i = 0; i < deploymentList.size(); i++) {
|
||||
deployments[i] = Long.toString(deploymentList.get(i).getId());
|
||||
}
|
||||
deploymentComboBox.setItems(FXCollections.observableArrayList(deployments));
|
||||
deploymentComboBox.getItems().add(0, "");
|
||||
if (selectedDeploymentData != null) {
|
||||
selectDeployment(selectedDeploymentData);
|
||||
}
|
||||
}
|
||||
|
||||
private void setServerName() {
|
||||
if (selectedServerData == null) {
|
||||
SharedServerData selectedServer = frontend.getData().getSelectedServer();
|
||||
if (selectedServer == null) {
|
||||
serverNameText.setText("N/A");
|
||||
} else {
|
||||
serverNameText.setText(selectedServerData.getName());
|
||||
serverNameText.setText(selectedServer.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void setBuildId() {
|
||||
if (selectedBuildData == null) {
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
buildIdText.setText("N/A");
|
||||
} else {
|
||||
buildIdText.setText(Long.toString(selectedBuildData.getId()));
|
||||
buildIdText.setText(Long.toString(selectedDeployment.getBuild().getId()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setDeploymentId() {
|
||||
if (selectedDeploymentData == null) {
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
deploymentIdText.setText("N/A");
|
||||
} else {
|
||||
deploymentIdText.setText(Long.toString(selectedDeploymentData.getId()));
|
||||
deploymentIdText.setText(Long.toString(selectedDeployment.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setStatus() {
|
||||
if (selectedDeploymentData == null) {
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
statusText.getStyleClass().setAll("white-label");
|
||||
statusText.setText("N/A");
|
||||
} else {
|
||||
if (selectedDeploymentData.getEndTime() == -1) {
|
||||
if (selectedDeployment.getEndTime() == 0) {
|
||||
statusText.getStyleClass().setAll("green-label");
|
||||
statusText.setText("Running");
|
||||
} else {
|
||||
statusText.getStyleClass().setAll("white-label");
|
||||
statusText.setText("Stopped at " + TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedDeploymentData.getEndTime())));
|
||||
statusText.setText("Stopped at " + TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedDeployment.getEndTime())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setStartTime() {
|
||||
if (selectedDeploymentData == null) {
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
startTimeText.setText("N/A");
|
||||
} else {
|
||||
startTimeText.setText(TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedDeploymentData.getStartTime())));
|
||||
startTimeText.setText(TimeUtilities.getDateString(TimeUtilities.convertUtcToLocal(selectedDeployment.getStartTime())));
|
||||
}
|
||||
}
|
||||
|
||||
private void setUptime() {
|
||||
if (selectedDeploymentData == null) {
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
uptimeText.setText("N/A");
|
||||
} else {
|
||||
long start = selectedDeploymentData.getStartTime();
|
||||
long end = selectedDeploymentData.getEndTime();
|
||||
if (end == -1) {
|
||||
long start = selectedDeployment.getStartTime();
|
||||
long end = selectedDeployment.getEndTime();
|
||||
if (end == 0) {
|
||||
uptimeText.setText(getTime(TimeUtilities.getTime()-start));
|
||||
} else {
|
||||
uptimeText.setText(getTime(end-start));
|
||||
@@ -206,10 +226,16 @@ public class DeploymentTab extends GridPane implements Initializable {
|
||||
}
|
||||
|
||||
private void setLog() {
|
||||
if (selectedDeploymentData == null) {
|
||||
logText.setText(" ");
|
||||
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
|
||||
if (selectedDeployment == null) {
|
||||
logTextArea.setText("");
|
||||
} else {
|
||||
logText.setText(" ");
|
||||
double pos = logTextArea.getScrollTop();
|
||||
int anchor = logTextArea.getAnchor();
|
||||
int caret = logTextArea.getCaretPosition();
|
||||
logTextArea.setText(selectedDeployment.getOutput());
|
||||
logTextArea.setScrollTop(pos);
|
||||
logTextArea.selectRange(anchor, caret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,4 +267,17 @@ public class DeploymentTab extends GridPane implements Initializable {
|
||||
void onDeploymentChanged(SharedDeploymentData deployment);
|
||||
}
|
||||
|
||||
private class DeploymentStringConverter extends StringConverter<SharedDeploymentData> {
|
||||
|
||||
public String toString(SharedDeploymentData deployment) {
|
||||
return "D " + deployment.getId() + " - B " + deployment.getBuild().getId();
|
||||
}
|
||||
|
||||
public SharedDeploymentData fromString(String string) {
|
||||
String [] parts = string.split(" ");
|
||||
return frontend.getData().getDeployment(Long.parseLong(parts[1]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,27 +28,34 @@
|
||||
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
|
||||
import com.projectswg.common.control.IntentManager;
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.javafx.FXMLController;
|
||||
import com.projectswg.common.javafx.FXMLUtilities;
|
||||
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.SharedDeploymentData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
import com.projectswg.lightspeed_frontend.javafx.FrontendFXMLLoader;
|
||||
import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
public class GeneralTab extends GridPane implements Initializable {
|
||||
public class GeneralTab implements FXMLController {
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> serverComboBox;
|
||||
private Parent rootGeneral;
|
||||
@FXML
|
||||
private ComboBox<SharedServerData> serverComboBox;
|
||||
@FXML
|
||||
private Label serverNameText;
|
||||
@FXML
|
||||
@@ -60,58 +67,76 @@ public class GeneralTab extends GridPane implements Initializable {
|
||||
@FXML
|
||||
private Label uptimeText;
|
||||
|
||||
private Frontend frontend;
|
||||
private SharedServerData selectedServerData;
|
||||
private SelectedServerChangedCallback callback;
|
||||
private final PswgBasicScheduledThread scheduledUpdater;
|
||||
private final Frontend frontend;
|
||||
|
||||
public GeneralTab() {
|
||||
frontend = null;
|
||||
selectedServerData = null;
|
||||
callback = null;
|
||||
FrontendFXMLLoader.load(this, "fxml/primary_tabs/General.fxml");
|
||||
this.scheduledUpdater = new PswgBasicScheduledThread("general-tab-updater", () -> requestUpdate());
|
||||
this.frontend = LightspeedFrontendGUI.FRONTEND;
|
||||
}
|
||||
|
||||
public void setFrontend(Frontend frontend) {
|
||||
this.frontend = frontend;
|
||||
}
|
||||
|
||||
public void setSelectedServerChangedCallback(SelectedServerChangedCallback callback) {
|
||||
this.callback = callback;
|
||||
@Override
|
||||
public Parent getRoot() {
|
||||
return rootGeneral;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
FXMLUtilities.onFxmlLoaded(this);
|
||||
serverNameText.getStyleClass().setAll("white-label");
|
||||
buildStatusText.getStyleClass().setAll("white-label");
|
||||
deploymentStatusText.getStyleClass().setAll("white-label");
|
||||
populationText.getStyleClass().setAll("white-label");
|
||||
uptimeText.getStyleClass().setAll("white-label");
|
||||
serverComboBox.selectionModelProperty().addListener((v, prev, next) -> {
|
||||
for (SharedServerData server : frontend.getData().getServers()) {
|
||||
if (server.getName().equals(v.getValue().getSelectedItem())) {
|
||||
selectedServerData = server;
|
||||
if (callback != null)
|
||||
callback.onServerChanged(server);
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateUi();
|
||||
serverComboBox.setConverter(new StringConverter<SharedServerData>() {
|
||||
public String toString(SharedServerData server) { return server.getName(); }
|
||||
public SharedServerData fromString(String string) { return frontend.getData().getServer(string); }
|
||||
});
|
||||
serverComboBox.getSelectionModel().selectedItemProperty().addListener((val, prev, next) -> {
|
||||
Log.d("selected server manually '%s'", next);
|
||||
frontend.getData().setSelectedServer(next);
|
||||
updateUiDetails();
|
||||
});
|
||||
IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> Platform.runLater(() -> updateUi()));
|
||||
updateUi();
|
||||
scheduledUpdater.startWithFixedRate(10000, 10000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() {
|
||||
scheduledUpdater.stop();
|
||||
}
|
||||
|
||||
private void requestUpdate() {
|
||||
SharedServerData selected = frontend.getData().getSelectedServer();
|
||||
if (selected != null) {
|
||||
frontend.loadServerDetailed(selected.getName(), response -> updateUi());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
updateServerList();
|
||||
if (selectedServerData == null) {
|
||||
Platform.runLater(() -> {
|
||||
updateServerList();
|
||||
updateUiDetails();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateServerList() {
|
||||
serverComboBox.setItems(frontend.getData().getServers());
|
||||
}
|
||||
|
||||
private void updateUiDetails() {
|
||||
SharedServerData selected = frontend.getData().getSelectedServer();
|
||||
if (selected == null) {
|
||||
setServerName("N/A");
|
||||
setEmptyBuildStatus();
|
||||
setEmptyDeploymentStatus();
|
||||
setEmptyPopulationText();
|
||||
setEmptyUptimeText();
|
||||
} else {
|
||||
SharedBuildData lastBuild = selectedServerData.getLastBuild();
|
||||
SharedDeploymentData lastDeployment = selectedServerData.getLastDeployment();
|
||||
setServerName(selectedServerData == null ? "N/A" : selectedServerData.getName());
|
||||
SharedBuildData lastBuild = selected.getLastBuild();
|
||||
SharedDeploymentData lastDeployment = selected.getLastDeployment();
|
||||
setServerName(selected == null ? "N/A" : selected.getName());
|
||||
if (lastBuild == null)
|
||||
setEmptyBuildStatus();
|
||||
else
|
||||
@@ -132,27 +157,6 @@ public class GeneralTab extends GridPane implements Initializable {
|
||||
}
|
||||
}
|
||||
|
||||
private void selectServer(SharedServerData server) {
|
||||
this.selectedServerData = server;
|
||||
serverComboBox.getSelectionModel().select(server.getName());
|
||||
if (callback != null)
|
||||
callback.onServerChanged(server);
|
||||
}
|
||||
|
||||
private void updateServerList() {
|
||||
if (frontend == null)
|
||||
return;
|
||||
List<SharedServerData> serverList = frontend.getData().getServers();
|
||||
String [] servers = new String[serverList.size()];
|
||||
for (int i = 0; i < serverList.size(); i++) {
|
||||
servers[i] = serverList.get(i).getName();
|
||||
}
|
||||
serverComboBox.setItems(FXCollections.observableArrayList(servers));
|
||||
if (selectedServerData != null) {
|
||||
selectServer(selectedServerData);
|
||||
}
|
||||
}
|
||||
|
||||
private void setServerName(String name) {
|
||||
serverNameText.setText(name);
|
||||
}
|
||||
|
||||
+3
-10
@@ -25,16 +25,9 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.lightspeed.frontend;
|
||||
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
TestConnect.class
|
||||
})
|
||||
public class TestFrontend {
|
||||
public class PrimaryTabData {
|
||||
|
||||
|
||||
}
|
||||
+11
-10
@@ -28,25 +28,26 @@
|
||||
package com.projectswg.lightspeed_frontend.intents;
|
||||
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
|
||||
public class ConnectionStateUpdateIntent extends Intent {
|
||||
public class InboundPacketIntent extends Intent {
|
||||
|
||||
private boolean connected;
|
||||
private Packet packet;
|
||||
|
||||
public ConnectionStateUpdateIntent() {
|
||||
this(false);
|
||||
public InboundPacketIntent() {
|
||||
|
||||
}
|
||||
|
||||
public ConnectionStateUpdateIntent(boolean connected) {
|
||||
setConnected(connected);
|
||||
public InboundPacketIntent(Packet packet) {
|
||||
setPacket(packet);
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
public Packet getPacket() {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
public void setPacket(Packet packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,11 +31,9 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import com.projectswg.lightspeed.frontend.TestFrontend;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
TestFrontend.class
|
||||
|
||||
})
|
||||
public class TestLightspeed {
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user