return info != null && schemeExtension != info.fileExtension
}
- private class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
- override fun read(): Element {
- val element = loadElement(bytes.inputStream().reader())
- if (externalInfo.hash == 0) {
- externalInfo.hash = element.getTreeHash()
- }
- return element
- }
- }
+ private inner class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
+ override fun read(): Element = loadElement(bytes.inputStream())
+
+ override fun updateDigest() {
+ schemeToInfo.forEachEntry({ k, v ->
+ if (v !== externalInfo) {
+ return@forEachEntry true
+ }
- @Suppress("UNCHECKED_CAST")
- try {
- externalInfo.digest = (processor.writeScheme(k as MUTABLE_SCHEME) as Element).digest()
- }
- catch (e: WriteExternalException) {
- LOG.error("Cannot update digest", e)
- }
- false
- })
- }
- }
-
- private fun loadScheme(fileName: CharSequence, input: InputStream, duringLoad: Boolean): MUTABLE_SCHEME? {
- try {
- return doLoadScheme(fileName, input, duringLoad)
- }
- catch (e: Throwable) {
- LOG.error("Cannot read scheme $fileName", e)
- return null
- }
- }
-
- private fun doLoadScheme(fileName: CharSequence, input: InputStream, duringLoad: Boolean): MUTABLE_SCHEME? {
+ private fun loadScheme(fileName: CharSequence, input: InputStream, duringLoad: Boolean): E? {
val extension = getFileExtension(fileName, false)
if (duringLoad && filesToDelete.isNotEmpty() && filesToDelete.contains(fileName.toString())) {
LOG.warn("Scheme file \"$fileName\" is not loaded because marked to delete")
return parent.findChild(fileName) ?: runWriteAction { parent.createChildData(requestor, fileName) }
}
+class DigestOutputStream(val digest: MessageDigest) : OutputStream() {
+ override fun write(b: Int) {
+ digest.update(b.toByte())
+ }
+
+ override fun write(b: ByteArray, off: Int, len: Int) {
+ digest.update(b, off, len)
+ }
+
+ override fun toString(): String {
+ return "[Digest Output Stream] " + digest.toString()
+ }
+}
+
+fun Element.digest(): ByteArray {
+ // sha-1 is enough, sha-256 is slower, see https://www.nayuki.io/page/native-hash-functions-for-java
+ val digest = MessageDigest.getInstance("SHA-1")
+ serializeElementToBinary(this, DigestOutputStream(digest))
+ return digest.digest()
++}
++
+ private inline fun catchAndLog(fileName: CharSequence, runnable: (fileName: CharSequence) -> Unit) {
+ try {
+ runnable(fileName)
+ }
+ catch (e: Throwable) {
+ LOG.error("Cannot read scheme $fileName", e)
+ }
}