From b75f7a7655a80fe25aa589586e49af29b3770afd Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Thu, 17 Mar 2022 19:45:58 +0800 Subject: [PATCH] temporary commit --- build.gradle | 7 + gradle.properties | 1 + src/main/java/module-info.java | 5 +- .../kotlin/net/woggioni/gbcs/Configuration.kt | 10 + .../woggioni/gbcs/GradleBuildCacheServer.kt | 27 ++- src/main/kotlin/net/woggioni/gbcs/Role.kt | 5 + src/main/kotlin/net/woggioni/gbcs/Xml.kt | 118 +++++++++++ src/main/resources/logging.properties | 3 +- .../net/woggioni/gbcs/gbcs-default.xml | 14 ++ src/main/resources/net/woggioni/gbcs/gbcs.xsd | 185 ++++++++++++++++++ 10 files changed, 358 insertions(+), 17 deletions(-) create mode 100644 src/main/kotlin/net/woggioni/gbcs/Configuration.kt create mode 100644 src/main/kotlin/net/woggioni/gbcs/Role.kt create mode 100644 src/main/kotlin/net/woggioni/gbcs/Xml.kt create mode 100644 src/main/resources/net/woggioni/gbcs/gbcs-default.xml create mode 100644 src/main/resources/net/woggioni/gbcs/gbcs.xsd diff --git a/build.gradle b/build.gradle index 0dad52e..0459f9a 100644 --- a/build.gradle +++ b/build.gradle @@ -11,10 +11,17 @@ group = 'net.woggioni' version = getProperty('gbcs.version') repositories { + maven { + url = 'https://woggioni.net/mvn' + content { + includeModule 'net.woggioni', 'jwo' + } + } mavenCentral() } dependencies { + implementation group: 'net.woggioni', name: 'jwo', version: getProperty('jwo.version') implementation group: 'org.slf4j', name: 'slf4j-api', version: getProperty('slf4j.version') implementation group: 'io.netty', name: 'netty-codec-http', version: getProperty('netty.version') diff --git a/gradle.properties b/gradle.properties index bbcbaa3..d108dcf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,7 @@ kotlin.version = 1.6.10 envelope.gradle.plugin.version = 1.0-SNAPSHOT lombok.gradle.plugin.version = 0.1 +jwo.version = 1.0-SNAPSHOT junit.jupiter.version = 5.8.2 netty.version = 4.1.74.Final h2.version = 2.1.210 diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index b0ffb10..3b9a4af 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,4 +1,6 @@ module net.woggioni.gbcs { + requires java.xml; + requires java.logging; requires kotlin.stdlib; requires io.netty.buffer; requires io.netty.transport; @@ -6,7 +8,8 @@ module net.woggioni.gbcs { requires io.netty.common; requires io.netty.handler; requires io.netty.codec; - requires java.logging; requires org.slf4j; + requires net.woggioni.jwo; + exports net.woggioni.gbcs; } \ No newline at end of file diff --git a/src/main/kotlin/net/woggioni/gbcs/Configuration.kt b/src/main/kotlin/net/woggioni/gbcs/Configuration.kt new file mode 100644 index 0000000..f888b85 --- /dev/null +++ b/src/main/kotlin/net/woggioni/gbcs/Configuration.kt @@ -0,0 +1,10 @@ +package net.woggioni.gbcs + +import java.nio.file.Path + +data class Configuration( + val cacheFolder : Path, + val host : String, + val port : Int, + val users : Map> +) \ No newline at end of file diff --git a/src/main/kotlin/net/woggioni/gbcs/GradleBuildCacheServer.kt b/src/main/kotlin/net/woggioni/gbcs/GradleBuildCacheServer.kt index a4999a9..692b5ce 100644 --- a/src/main/kotlin/net/woggioni/gbcs/GradleBuildCacheServer.kt +++ b/src/main/kotlin/net/woggioni/gbcs/GradleBuildCacheServer.kt @@ -34,10 +34,12 @@ import io.netty.handler.stream.ChunkedNioFile import io.netty.handler.stream.ChunkedWriteHandler import io.netty.util.concurrent.DefaultEventExecutorGroup import io.netty.util.concurrent.EventExecutorGroup +import net.woggioni.jwo.JWO import java.nio.channels.FileChannel import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths +import java.nio.file.StandardCopyOption import java.nio.file.StandardOpenOption import java.security.MessageDigest import java.util.AbstractMap.SimpleEntry @@ -208,8 +210,15 @@ class GradleBuildCacheServer { } val content = msg.content() val file = cacheDir.resolve(digestString(key.toByteArray())) - Files.newOutputStream(file).use { - content.readBytes(it, content.readableBytes()) + val tmpFile = Files.createTempFile(cacheDir, null, ".tmp") + try { + Files.newOutputStream(tmpFile).use { + content.readBytes(it, content.readableBytes()) + } + Files.move(tmpFile, file, StandardCopyOption.ATOMIC_MOVE) + } catch (t : Throwable) { + Files.delete(tmpFile) + throw t } val response = DefaultFullHttpResponse(msg.protocolVersion(), HttpResponseStatus.CREATED, Unpooled.copiedBuffer(key.toByteArray())) @@ -268,18 +277,6 @@ class GradleBuildCacheServer { GradleBuildCacheServer().run() } - private val hexArray = "0123456789ABCDEF".toCharArray() - - fun bytesToHex(bytes: ByteArray): String { - val hexChars = CharArray(bytes.size * 2) - for (j in bytes.indices) { - val v: Int = bytes[j].toInt().and(0xFF) - hexChars[j * 2] = hexArray[v ushr 4] - hexChars[j * 2 + 1] = hexArray[v and 0x0F] - } - return String(hexChars) - } - fun digest(data : ByteArray, md : MessageDigest = MessageDigest.getInstance("MD5")) : ByteArray { md.update(data) @@ -288,7 +285,7 @@ class GradleBuildCacheServer { fun digestString(data : ByteArray, md : MessageDigest = MessageDigest.getInstance("MD5")) : String { - return bytesToHex(digest(data, md)) + return JWO.bytesToHex(digest(data, md)) } } } \ No newline at end of file diff --git a/src/main/kotlin/net/woggioni/gbcs/Role.kt b/src/main/kotlin/net/woggioni/gbcs/Role.kt new file mode 100644 index 0000000..a9a5a2a --- /dev/null +++ b/src/main/kotlin/net/woggioni/gbcs/Role.kt @@ -0,0 +1,5 @@ +package net.woggioni.gbcs + +enum class Role { + Reader, Writer +} \ No newline at end of file diff --git a/src/main/kotlin/net/woggioni/gbcs/Xml.kt b/src/main/kotlin/net/woggioni/gbcs/Xml.kt new file mode 100644 index 0000000..cdc5c4e --- /dev/null +++ b/src/main/kotlin/net/woggioni/gbcs/Xml.kt @@ -0,0 +1,118 @@ +package net.woggioni.gbcs + +import org.slf4j.LoggerFactory +import org.w3c.dom.Document +import org.xml.sax.ErrorHandler +import org.xml.sax.SAXNotRecognizedException +import org.xml.sax.SAXNotSupportedException +import org.xml.sax.SAXParseException +import java.net.URL +import javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD +import javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA +import javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING +import javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI +import javax.xml.parsers.DocumentBuilder +import javax.xml.parsers.DocumentBuilderFactory +import javax.xml.validation.Schema +import javax.xml.validation.SchemaFactory + + +object Xml { + + private class XmlErrorHandler(private val fileURL: URL) : ErrorHandler { + + companion object { + private val log = LoggerFactory.getLogger(XmlErrorHandler::class.java) + } + + override fun warning(ex: SAXParseException) { + log.warn( + "Problem at {}:{}:{} parsing deployment configuration: {}", + fileURL, ex.lineNumber, ex.columnNumber, ex.message + ) + } + + override fun error(ex: SAXParseException) { + log.error( + "Problem at {}:{}:{} parsing deployment configuration: {}", + fileURL, ex.lineNumber, ex.columnNumber, ex.message + ) + throw ex + } + + override fun fatalError(ex: SAXParseException) { + log.error( + "Problem at {}:{}:{} parsing deployment configuration: {}", + fileURL, ex.lineNumber, ex.columnNumber, ex.message + ) + throw ex + } + } + + private fun disableProperty(dbf: DocumentBuilderFactory, propertyName: String) { + try { + dbf.setAttribute(propertyName, "") + } catch (iae: IllegalArgumentException) { + // Property not supported. + } + } + + private fun disableProperty(sf: SchemaFactory, propertyName: String) { + try { + sf.setProperty(propertyName, "") + } catch (ex: SAXNotRecognizedException) { + // Property not supported. + } catch (ex: SAXNotSupportedException) { + } + } + + private fun getSchema(schemaResourceURL: String): Schema { + val sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI) + sf.setFeature(FEATURE_SECURE_PROCESSING, true) + disableProperty(sf, ACCESS_EXTERNAL_SCHEMA) + disableProperty(sf, ACCESS_EXTERNAL_DTD) + val schemaUrl: URL = Xml::class.java.classLoader.getResource(schemaResourceURL) + ?: throw IllegalStateException(String.format("Missing configuration schema '%s'", schemaResourceURL)) + return sf.newSchema(schemaUrl) + } + + private fun newDocumentBuilderFactory(schemaResourceURL: String?): DocumentBuilderFactory { + val dbf = DocumentBuilderFactory.newInstance() + dbf.setFeature(FEATURE_SECURE_PROCESSING, true) + disableProperty(dbf, ACCESS_EXTERNAL_SCHEMA) + disableProperty(dbf, ACCESS_EXTERNAL_DTD) + dbf.isExpandEntityReferences = false + dbf.isIgnoringComments = true + dbf.isNamespaceAware = true + val sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI) + sf.setFeature(FEATURE_SECURE_PROCESSING, true) + disableProperty(sf, ACCESS_EXTERNAL_SCHEMA) + disableProperty(sf, ACCESS_EXTERNAL_DTD) + if (schemaResourceURL != null) { + dbf.schema = getSchema(schemaResourceURL) + } + return dbf + } + + fun newDocumentBuilder(resource: URL, schemaResourceURL: String?): DocumentBuilder { + val db = newDocumentBuilderFactory(schemaResourceURL).newDocumentBuilder() + db.setErrorHandler(XmlErrorHandler(resource)) + return db + } + + fun parseXmlResource(resource: URL, schemaResourceURL: String?): Document { + val db = newDocumentBuilder(resource, schemaResourceURL) + return resource.openStream().use(db::parse) + } + + fun newDocumentBuilder(resource: URL): DocumentBuilder { + val db = newDocumentBuilderFactory(null).newDocumentBuilder() + db.setErrorHandler(XmlErrorHandler(resource)) + return db + } + + fun parseXmlResource(resource: URL): Document { + val db = newDocumentBuilder(resource, null) + return resource.openStream().use(db::parse) + } +} diff --git a/src/main/resources/logging.properties b/src/main/resources/logging.properties index 8a2887d..744af31 100644 --- a/src/main/resources/logging.properties +++ b/src/main/resources/logging.properties @@ -4,5 +4,6 @@ handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = FINEST java.util.logging.ConsoleHandler.filter = -java.util.logging.ConsoleHandler.formatter = +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = %1$tF %1$tT [%4$s] %2$s %5$s %n java.util.logging.ConsoleHandler.encoding = \ No newline at end of file diff --git a/src/main/resources/net/woggioni/gbcs/gbcs-default.xml b/src/main/resources/net/woggioni/gbcs/gbcs-default.xml new file mode 100644 index 0000000..bd636d6 --- /dev/null +++ b/src/main/resources/net/woggioni/gbcs/gbcs-default.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/net/woggioni/gbcs/gbcs.xsd b/src/main/resources/net/woggioni/gbcs/gbcs.xsd new file mode 100644 index 0000000..258554c --- /dev/null +++ b/src/main/resources/net/woggioni/gbcs/gbcs.xsd @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +