Skip to content

Commit

Permalink
improv: Validate settings and inform about unsaved changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Griefed committed Sep 17, 2023
1 parent 6bb52f1 commit 4a4bb7f
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 20 deletions.
1 change: 1 addition & 0 deletions serverpackcreator-gui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
api("com.formdev:svgSalamander:1.1.4")
api("net.java.balloontip:balloontip:1.2.4.1")
api("com.github.dyorgio.runtime:run-as-root:1.2.3")
api("com.cronutils:cron-utils:9.2.1")

testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.3")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ import de.griefed.serverpackcreator.gui.window.configs.components.ComponentResiz
import de.griefed.serverpackcreator.gui.window.settings.components.*
import java.awt.event.ActionListener
import java.io.File
import java.net.MalformedURLException
import java.net.URL
import javax.swing.DefaultComboBoxModel
import javax.swing.JCheckBox

Check warning on line 36 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/settings/GlobalSettings.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused import directive

Unused import directive
import javax.swing.JComboBox

Check warning on line 37 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/settings/GlobalSettings.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused import directive

Unused import directive
import javax.swing.JFileChooser

class GlobalSettings(
guiProps: GuiProps,
private val guiProps: GuiProps,
private val apiProperties: ApiProperties,
componentResizer: ComponentResizer,
mainFrame: MainFrame,
Expand Down Expand Up @@ -351,11 +352,61 @@ class GlobalSettings(
}

override fun validateSettings(): List<String> {
return listOf("")
val errors = mutableListOf<String>()
if (!homeSetting.file.absoluteFile.isDirectory || !homeSetting.file.absoluteFile.canWrite()) {
homeIcon.error("Home-directory either does not exist or is not writable.")
errors.add("Home-directory either does not exist or is not writable.")
} else {
homeIcon.info()
}

if (!javaSetting.file.absoluteFile.isFile || !javaSetting.file.absoluteFile.canRead() || !javaSetting.file.absoluteFile.canExecute()) {
javaIcon.error("Java executable/binary either does not exist, is not readable, or is not executable.")
errors.add("Java executable/binary either does not exist, is not readable, or is not executable.")
} else {
javaIcon.info()
}

if (!serverPacksSetting.file.absoluteFile.isDirectory || !serverPacksSetting.file.absoluteFile.canWrite()) {
serverPacksIcon.error("Server packs directory either does not exist or is not writable.")
errors.add("Server packs directory either does not exist or is not writable.")
} else {
serverPacksIcon.info()
}

if (zipSetting.text.matches(guiProps.whitespace)) {
zipIcon.error("Must not end with ','!")
errors.add("Must not end with ','!")
} else {
zipIcon.info()
}

if (inclusionsSetting.text.matches(guiProps.whitespace)) {
inclusionsIcon.error("Must not end with ','!")
errors.add("Must not end with ','!")
} else {
inclusionsIcon.info()
}

if (scriptSetting.text.matches(guiProps.whitespace)) {
scriptIcon.error("Must not end with ','!")
errors.add("Must not end with ','!")
} else {
scriptIcon.info()
}

try {
URL(fallbackURLSetting.text)
fallbackURLIcon.info()
} catch (ex: MalformedURLException) {
fallbackURLIcon.error("Invalid URL format!")
errors.add("Invalid URL format!")
}
return errors.toList()
}

override fun hasUnsavedChanges(): Boolean {
return homeSetting.file != apiProperties.homeDirectory.absoluteFile ||
val changes = homeSetting.file != apiProperties.homeDirectory.absoluteFile ||
javaSetting.file != File(apiProperties.javaPath).absoluteFile ||
serverPacksSetting.file != apiProperties.serverPacksDirectory.absoluteFile ||
zipSetting.text != apiProperties.zipArchiveExclusions.joinToString(", ") ||
Expand All @@ -372,5 +423,11 @@ class GlobalSettings(
cleanupSetting.isSelected != apiProperties.isServerPackCleanupEnabled ||
snapshotsSetting.isSelected != apiProperties.isMinecraftPreReleasesAvailabilityEnabled ||
autodetectionSetting.isSelected != apiProperties.isAutoExcludingModsEnabled
if (changes) {
title.showWarningIcon()
} else {
title.hideWarningIcon()
}
return changes
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,30 @@ class GuiSettings(
}

override fun validateSettings(): List<String> {
return listOf("")
val errors = mutableListOf<String>()
if (fontSizeSetting.value < 8 || fontSizeSetting.value > 76) {
fontSizeIcon.error("Font size must be a value from 8 to 76.")
errors.add("Font size must be a value from 8 to 76.")
} else {
fontSizeIcon.info()
}
if (errors.isNotEmpty()) {
title.setAndShowErrorIcon("Your GUI settings contain errors!")
} else {
title.hideErrorIcon()
}
return errors.toList()
}

override fun hasUnsavedChanges(): Boolean {
return fontSizeSetting.value != guiProps.fontSize ||
startFocusSetting.isSelected != guiProps.startFocusEnabled ||
generationFocusSetting.isSelected != guiProps.generationFocusEnabled
val changes = fontSizeSetting.value != guiProps.fontSize ||
startFocusSetting.isSelected != guiProps.startFocusEnabled ||
generationFocusSetting.isSelected != guiProps.generationFocusEnabled
if (changes) {
title.showWarningIcon()
} else {
title.hideWarningIcon()
}
return changes
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import de.griefed.serverpackcreator.gui.window.MainFrame
import de.griefed.serverpackcreator.gui.window.configs.components.ComponentResizer
import de.griefed.serverpackcreator.gui.window.settings.components.Editor
import de.griefed.serverpackcreator.gui.window.settings.components.SettingsCheckTimer
import de.griefed.serverpackcreator.gui.window.settings.components.SettingsHandling
import de.griefed.serverpackcreator.gui.window.settings.components.SettingsTitle
import java.awt.BorderLayout
import java.awt.event.ActionListener
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
*
* The full license can be found at https:github.com/Griefed/ServerPackCreator/blob/main/LICENSE
*/
package de.griefed.serverpackcreator.gui.window.settings.components
package de.griefed.serverpackcreator.gui.window.settings

import de.griefed.serverpackcreator.api.ApiProperties
import de.griefed.serverpackcreator.gui.GuiProps
import de.griefed.serverpackcreator.gui.components.BalloonTipButton
import de.griefed.serverpackcreator.gui.window.MainFrame
import de.griefed.serverpackcreator.gui.window.settings.SettingsEditorsTab
import de.griefed.serverpackcreator.gui.window.settings.components.PropertiesChooser
import dyorgio.runtime.run.`as`.root.RootExecutor
import net.miginfocom.swing.MigLayout
import java.io.File
Expand Down Expand Up @@ -107,7 +107,7 @@ class SettingsHandling(
settingsEditorsTab.gui.saveSettings()
settingsEditorsTab.webservice.saveSettings()
apiProperties.saveProperties(apiProperties.serverPackCreatorPropertiesFile)
if (!apiProperties.overrideProperties.canWrite()) {
if (!apiProperties.overrideProperties.parentFile.canWrite()) {
if (rootWarning() == JOptionPane.OK_OPTION) {
val overridePath = apiProperties.overrideProperties.absolutePath
val overrides = apiProperties.overridesAsString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
*/
package de.griefed.serverpackcreator.gui.window.settings

import com.cronutils.model.CronType
import com.cronutils.model.definition.CronDefinitionBuilder
import com.cronutils.parser.CronParser
import de.griefed.serverpackcreator.api.ApiProperties
import de.griefed.serverpackcreator.gui.GuiProps
import de.griefed.serverpackcreator.gui.components.*
Expand All @@ -36,6 +39,9 @@ class WebserviceSettings(
changeListener: ChangeListener
) : Editor("Webservice", guiProps) {

private val cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING)
private val cronParser = CronParser(cronDefinition)

val artemisDataDirectoryIcon = StatusIcon(guiProps, "Data directory for Artemis Queue System")

Check notice on line 45 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/settings/WebserviceSettings.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'artemisDataDirectoryIcon' could be private
val artemisDataDirectoryLabel = ElementLabel("Artemis Data Directory")

Check notice on line 46 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/settings/WebserviceSettings.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'artemisDataDirectoryLabel' could be private
val artemisDataDirectorySetting = ScrollTextFileField(guiProps,apiProperties.artemisDataDirectory.absoluteFile, documentChangeListener)

Check notice on line 47 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/settings/WebserviceSettings.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'artemisDataDirectorySetting' could be private
Expand Down Expand Up @@ -199,17 +205,89 @@ class WebserviceSettings(
}

override fun validateSettings(): List<String> {
return listOf("")
val errors = mutableListOf<String>()
if (!artemisDataDirectorySetting.file.absoluteFile.isDirectory || !artemisDataDirectorySetting.file.absoluteFile.canWrite()) {
artemisDataDirectoryIcon.error("Artemis Data directory either does not exist or is not writable.")
errors.add("Artemis Data directory either does not exist or is not writable.")
} else {
artemisDataDirectoryIcon.info()
}

if (artemisQueueMaxDiskUsageSetting.value < 10 || artemisQueueMaxDiskUsageSetting.value > 90 ) {
artemisQueueMaxDiskUsageIcon.error("Artemis max disk usage must be a value from 10 to 90.")
errors.add("Artemis max disk usage must be a value from 10 to 90.")
} else {
artemisQueueMaxDiskUsageIcon.info()
}

if (!databaseFileSetting.file.absoluteFile.parentFile.isDirectory || !databaseFileSetting.file.absoluteFile.parentFile.canWrite()) {
databaseFileIcon.error("Database directory does not exist or is not writable.")
errors.add("Database directory does not exist or is not writable.")
} else {
databaseFileIcon.info()
}

try {
cronParser.parse(cleanupScheduleSetting.text).validate()
cleanupScheduleIcon.info()
} catch (ex: IllegalArgumentException) {
cleanupScheduleIcon.error("Invalid Cleanup Schedule QUARTZ CRON expression.")
errors.add("Invalid Cleanup Schedule QUARTZ CRON expression.")
}

if (!logDirectorySetting.file.absoluteFile.isDirectory || !logDirectorySetting.file.absoluteFile.canWrite()) {
logDirectoryIcon.error("Tomcat Log directory does not exist or is not writable.")
errors.add("Tomcat Log directory does not exist or is not writable.")
} else {
logDirectoryIcon.info()
}

if (!baseDirSetting.file.absoluteFile.isDirectory || !baseDirSetting.file.absoluteFile.canWrite()) {
baseDirIcon.error("Tomcat base-directory does not exist or is not writable.")
errors.add("Tomcat base-directory does not exist or is not writable.")
} else {
baseDirIcon.info()
}

try {
cronParser.parse(versionScheduleSetting.text).validate()
versionScheduleIcon.info()
} catch (ex: IllegalArgumentException) {
versionScheduleIcon.error("Invalid Version Update Schedule QUARTZ CRON expression.")
errors.add("Invalid Version Update Schedule QUARTZ CRON expression.")
}

try {
cronParser.parse(databaseCleanupScheduleSetting.text).validate()
databaseCleanupScheduleIcon.info()
} catch (ex: IllegalArgumentException) {
databaseCleanupScheduleIcon.error("Invalid Database Cleanup Schedule QUARTZ CRON expression.")
errors.add("Invalid Database Cleanup Schedule QUARTZ CRON expression.")
}

if (errors.isNotEmpty()) {
title.setAndShowErrorIcon("Your Webservice settings contain errors!")
} else {
title.hideErrorIcon()
}

return errors.toList()
}

override fun hasUnsavedChanges(): Boolean {
return artemisDataDirectorySetting.file != apiProperties.artemisDataDirectory.absoluteFile ||
artemisQueueMaxDiskUsageSetting.value != apiProperties.artemisQueueMaxDiskUsage ||
databaseFileSetting.file != apiProperties.serverPackCreatorDatabase.absoluteFile ||
cleanupScheduleSetting.text != apiProperties.webserviceCleanupSchedule ||
logDirectorySetting.file != apiProperties.tomcatLogsDirectory.absoluteFile ||
baseDirSetting.file != apiProperties.tomcatBaseDirectory.absoluteFile ||
versionScheduleSetting.text != apiProperties.webserviceVersionSchedule ||
databaseCleanupScheduleSetting.text != apiProperties.webserviceDatabaseCleanupSchedule
val changes = artemisDataDirectorySetting.file != apiProperties.artemisDataDirectory.absoluteFile ||
artemisQueueMaxDiskUsageSetting.value != apiProperties.artemisQueueMaxDiskUsage ||
databaseFileSetting.file != apiProperties.serverPackCreatorDatabase.absoluteFile ||
cleanupScheduleSetting.text != apiProperties.webserviceCleanupSchedule ||
logDirectorySetting.file != apiProperties.tomcatLogsDirectory.absoluteFile ||
baseDirSetting.file != apiProperties.tomcatBaseDirectory.absoluteFile ||
versionScheduleSetting.text != apiProperties.webserviceVersionSchedule ||
databaseCleanupScheduleSetting.text != apiProperties.webserviceDatabaseCleanupSchedule
if (changes) {
title.showWarningIcon()
} else {
title.hideWarningIcon()
}
return changes
}
}

0 comments on commit 4a4bb7f

Please sign in to comment.