Kotlin logging

This commit is contained in:
xis 2023-10-10 15:13:59 +02:00
parent 4da6b541d8
commit 4e8ddbb5bf
15 changed files with 180 additions and 176 deletions

View file

@ -23,6 +23,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin' implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect' implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'io.github.microutils:kotlin-logging:3.0.5'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.mariadb.jdbc:mariadb-java-client:3.2.0' implementation 'org.mariadb.jdbc:mariadb-java-client:3.2.0'

View file

@ -2,10 +2,10 @@ package net.schowek.nextclouddlna.controller
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse import jakarta.servlet.http.HttpServletResponse
import mu.KLogging
import net.schowek.nextclouddlna.nextcloud.content.ContentGroup.* import net.schowek.nextclouddlna.nextcloud.content.ContentGroup.*
import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider
import net.schowek.nextclouddlna.nextcloud.content.MediaFormat import net.schowek.nextclouddlna.nextcloud.content.MediaFormat
import net.schowek.nextclouddlna.util.Logging
import org.jupnp.support.model.Protocol import org.jupnp.support.model.Protocol
import org.jupnp.support.model.ProtocolInfo import org.jupnp.support.model.ProtocolInfo
import org.jupnp.support.model.dlna.* import org.jupnp.support.model.dlna.*
@ -25,7 +25,7 @@ import java.util.*
@RestController @RestController
class ContentController( class ContentController(
private val contentTreeProvider: ContentTreeProvider private val contentTreeProvider: ContentTreeProvider
) : Logging { ) {
@RequestMapping(method = [RequestMethod.GET, RequestMethod.HEAD], value = ["/c/{id}"]) @RequestMapping(method = [RequestMethod.GET, RequestMethod.HEAD], value = ["/c/{id}"])
@ResponseBody @ResponseBody
fun getResource( fun getResource(
@ -73,5 +73,6 @@ class ContentController(
} }
return DLNAProtocolInfo(Protocol.HTTP_GET, ProtocolInfo.WILDCARD, mediaFormat.mime, attributes) return DLNAProtocolInfo(Protocol.HTTP_GET, ProtocolInfo.WILDCARD, mediaFormat.mime, attributes)
} }
companion object: KLogging()
} }

View file

@ -41,7 +41,7 @@ class DlnaService(
} }
} }
private inner class MyUpnpServiceConfiguration : DefaultUpnpServiceConfiguration() { private inner class MyUpnpServiceConfiguration : DefaultUpnpServiceConfiguration(8081) {
override fun createStreamClient(): StreamClient<*> { override fun createStreamClient(): StreamClient<*> {
return ApacheStreamClient( return ApacheStreamClient(
ApacheStreamClientConfiguration(syncProtocolExecutorService) ApacheStreamClientConfiguration(syncProtocolExecutorService)

View file

@ -1,7 +1,7 @@
package net.schowek.nextclouddlna.dlna.media package net.schowek.nextclouddlna.dlna.media
import mu.KLogging
import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider
import net.schowek.nextclouddlna.util.Logging
import org.jupnp.support.contentdirectory.AbstractContentDirectoryService import org.jupnp.support.contentdirectory.AbstractContentDirectoryService
import org.jupnp.support.contentdirectory.ContentDirectoryErrorCode import org.jupnp.support.contentdirectory.ContentDirectoryErrorCode
import org.jupnp.support.contentdirectory.ContentDirectoryException import org.jupnp.support.contentdirectory.ContentDirectoryException
@ -25,7 +25,7 @@ class ContentDirectoryService(
) : AbstractContentDirectoryService( ) : AbstractContentDirectoryService(
mutableListOf("dc:title", "upnp:class"), // also "dc:creator", "dc:date", "res@size" mutableListOf("dc:title", "upnp:class"), // also "dc:creator", "dc:date", "res@size"
mutableListOf("dc:title") mutableListOf("dc:title")
), Logging { ) {
/** /**
* Root is requested with objectID="0". * Root is requested with objectID="0".
@ -77,7 +77,7 @@ class ContentDirectoryService(
} }
} }
companion object { companion object : KLogging() {
@Throws(Exception::class) @Throws(Exception::class)
private fun toRangedResult( private fun toRangedResult(
containers: List<Container>, containers: List<Container>,

View file

@ -1,8 +1,8 @@
package net.schowek.nextclouddlna.dlna.media package net.schowek.nextclouddlna.dlna.media
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
import mu.KLogging
import net.schowek.nextclouddlna.util.ExternalUrls import net.schowek.nextclouddlna.util.ExternalUrls
import net.schowek.nextclouddlna.util.Logging
import org.jupnp.model.meta.* import org.jupnp.model.meta.*
import org.jupnp.model.types.UDADeviceType import org.jupnp.model.types.UDADeviceType
import org.jupnp.model.types.UDN.uniqueSystemIdentifier import org.jupnp.model.types.UDN.uniqueSystemIdentifier
@ -21,7 +21,7 @@ class MediaServer(
@Value("\${server.friendlyName}") @Value("\${server.friendlyName}")
private val friendlyName: String, private val friendlyName: String,
private val externalUrls: ExternalUrls private val externalUrls: ExternalUrls
) : Logging { ) {
val device = LocalDevice( val device = LocalDevice(
DeviceIdentity(uniqueSystemIdentifier("DLNAtoad-MediaServer"), 300), DeviceIdentity(uniqueSystemIdentifier("DLNAtoad-MediaServer"), 300),
UDADeviceType(DEVICE_TYPE, VERSION), UDADeviceType(DEVICE_TYPE, VERSION),
@ -34,7 +34,7 @@ class MediaServer(
logger.info("uniqueSystemIdentifier: {} ({})", device.identity.udn, friendlyName) logger.info("uniqueSystemIdentifier: {} ({})", device.identity.udn, friendlyName)
} }
companion object { companion object : KLogging() {
private const val DEVICE_TYPE = "MediaServer" private const val DEVICE_TYPE = "MediaServer"
private const val VERSION = 1 private const val VERSION = 1
const val ICON_FILENAME = "icon.png" const val ICON_FILENAME = "icon.png"

View file

@ -1,6 +1,6 @@
package net.schowek.nextclouddlna.dlna.transport package net.schowek.nextclouddlna.dlna.transport
import net.schowek.nextclouddlna.util.Logging import mu.KLogging
import org.apache.http.* import org.apache.http.*
import org.apache.http.client.ResponseHandler import org.apache.http.client.ResponseHandler
import org.apache.http.client.config.RequestConfig import org.apache.http.client.config.RequestConfig
@ -30,7 +30,7 @@ import java.util.concurrent.Callable
class ApacheStreamClient( class ApacheStreamClient(
private val configuration: ApacheStreamClientConfiguration private val configuration: ApacheStreamClientConfiguration
) : Logging, AbstractStreamClient<ApacheStreamClientConfiguration?, HttpRequestBase>() { ) : AbstractStreamClient<ApacheStreamClientConfiguration?, HttpRequestBase>() {
private val clientConnectionManager: PoolingHttpClientConnectionManager private val clientConnectionManager: PoolingHttpClientConnectionManager
private val httpClient: CloseableHttpClient private val httpClient: CloseableHttpClient
@ -230,7 +230,7 @@ class ApacheStreamClient(
} }
} }
companion object { companion object : KLogging() {
private fun addHeaders(httpMessage: HttpMessage, headers: Headers) { private fun addHeaders(httpMessage: HttpMessage, headers: Headers) {
for ((key, value1) in headers) { for ((key, value1) in headers) {
for (value in value1) { for (value in value1) {

View file

@ -1,7 +1,7 @@
package net.schowek.nextclouddlna.dlna.transport package net.schowek.nextclouddlna.dlna.transport
import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpExchange
import net.schowek.nextclouddlna.util.Logging import mu.KLogging
import org.jupnp.model.message.* import org.jupnp.model.message.*
import org.jupnp.protocol.ProtocolFactory import org.jupnp.protocol.ProtocolFactory
import org.jupnp.transport.spi.UpnpStream import org.jupnp.transport.spi.UpnpStream
@ -13,38 +13,34 @@ import java.net.HttpURLConnection
abstract class MyHttpExchangeUpnpStream( abstract class MyHttpExchangeUpnpStream(
protocolFactory: ProtocolFactory?, protocolFactory: ProtocolFactory,
val httpExchange: HttpExchange private val httpExchange: HttpExchange
) : Logging, UpnpStream(protocolFactory) { ) : UpnpStream(protocolFactory) {
override fun run() { override fun run() {
try { try {
val xchng = httpExchange
// Status // Status
val requestMessage = StreamRequestMessage( val requestMessage = StreamRequestMessage(
UpnpRequest.Method.getByHttpName(xchng.requestMethod), UpnpRequest.Method.getByHttpName(httpExchange.requestMethod),
xchng.requestURI httpExchange.requestURI
) )
if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) { if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) {
logger.warn("Method not supported by UPnP stack: {}", xchng.requestMethod) logger.warn("Method not supported by UPnP stack: {}", httpExchange.requestMethod)
throw RuntimeException("Method not supported: {}" + xchng.requestMethod) throw RuntimeException("Method not supported: {}" + httpExchange.requestMethod)
} }
// Protocol // Protocol
requestMessage.operation.httpMinorVersion = if (xchng.protocol.uppercase() == "HTTP/1.1") 1 else 0 requestMessage.operation.httpMinorVersion = if (httpExchange.protocol.uppercase() == "HTTP/1.1") 1 else 0
// Connection wrapper // Connection wrapper
requestMessage.connection = createConnection() requestMessage.connection = createConnection()
// Headers // Headers
requestMessage.headers = UpnpHeaders(xchng.requestHeaders) requestMessage.headers = UpnpHeaders(httpExchange.requestHeaders)
// Body // Body
val bodyBytes: ByteArray val bodyBytes: ByteArray
var inputStream: InputStream? = null var inputStream: InputStream? = null
try { try {
inputStream = xchng.requestBody inputStream = httpExchange.requestBody
bodyBytes = IO.readBytes(inputStream) bodyBytes = IO.readBytes(inputStream)
} finally { } finally {
inputStream?.close() inputStream?.close()
@ -67,13 +63,13 @@ abstract class MyHttpExchangeUpnpStream(
// Return the response // Return the response
if (responseMessage != null) { if (responseMessage != null) {
// Headers // Headers
xchng.responseHeaders.putAll(responseMessage.headers) httpExchange.responseHeaders.putAll(responseMessage.headers)
// Body // Body
val responseBodyBytes = if (responseMessage.hasBody()) responseMessage.bodyBytes else null val responseBodyBytes = if (responseMessage.hasBody()) responseMessage.bodyBytes else null
val contentLength = responseBodyBytes?.size ?: -1 val contentLength = responseBodyBytes?.size ?: -1
logger.info("Sending HTTP response message: $responseMessage with content length: $contentLength") logger.info("Sending HTTP response message: $responseMessage with content length: $contentLength")
xchng.sendResponseHeaders(responseMessage.operation.statusCode, contentLength.toLong()) httpExchange.sendResponseHeaders(responseMessage.operation.statusCode, contentLength.toLong())
if (responseBodyBytes!!.isNotEmpty()) { if (responseBodyBytes!!.isNotEmpty()) {
logger.debug(" Response body: " + responseMessage.body) logger.debug(" Response body: " + responseMessage.body)
} }
@ -81,7 +77,7 @@ abstract class MyHttpExchangeUpnpStream(
logger.debug("Response message has body, writing bytes to stream...") logger.debug("Response message has body, writing bytes to stream...")
var outputStream: OutputStream? = null var outputStream: OutputStream? = null
try { try {
outputStream = xchng.responseBody outputStream = httpExchange.responseBody
IO.writeBytes(outputStream, responseBodyBytes) IO.writeBytes(outputStream, responseBodyBytes)
outputStream.flush() outputStream.flush()
} finally { } finally {
@ -91,11 +87,10 @@ abstract class MyHttpExchangeUpnpStream(
} else { } else {
// If it's null, it's 404, everything else needs a proper httpResponse // If it's null, it's 404, everything else needs a proper httpResponse
logger.info("Sending HTTP response status: " + HttpURLConnection.HTTP_NOT_FOUND) logger.info("Sending HTTP response status: " + HttpURLConnection.HTTP_NOT_FOUND)
xchng.sendResponseHeaders(HttpURLConnection.HTTP_NOT_FOUND, -1) httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_NOT_FOUND, -1)
} }
responseSent(responseMessage) responseSent(responseMessage)
} catch (t: Throwable) { } catch (t: Throwable) {
// You definitely want to catch all Exceptions here, otherwise the server will // You definitely want to catch all Exceptions here, otherwise the server will
// simply close the socket and you get an "unexpected end of file" on the client. // simply close the socket and you get an "unexpected end of file" on the client.
// The same is true if you just rethrow an IOException - it is a mystery why it // The same is true if you just rethrow an IOException - it is a mystery why it
@ -116,5 +111,7 @@ abstract class MyHttpExchangeUpnpStream(
} }
protected abstract fun createConnection(): Connection? protected abstract fun createConnection(): Connection?
companion object: KLogging()
} }

View file

@ -5,7 +5,7 @@ import org.jupnp.transport.spi.StreamServerConfiguration
class MyStreamServerConfiguration( class MyStreamServerConfiguration(
private val listenPort: Int private val listenPort: Int
) : StreamServerConfiguration { ) : StreamServerConfiguration {
var tcpConnectionBacklog = 0 val tcpConnectionBacklog = 0
override fun getListenPort(): Int { override fun getListenPort(): Int {
return listenPort return listenPort
} }

View file

@ -3,7 +3,7 @@ package net.schowek.nextclouddlna.dlna.transport
import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer import com.sun.net.httpserver.HttpServer
import net.schowek.nextclouddlna.util.Logging import mu.KLogging
import org.jupnp.model.message.Connection import org.jupnp.model.message.Connection
import org.jupnp.transport.Router import org.jupnp.transport.Router
import org.jupnp.transport.spi.InitializationException import org.jupnp.transport.spi.InitializationException
@ -15,14 +15,14 @@ import java.net.InetSocketAddress
class MyStreamServerImpl( class MyStreamServerImpl(
private val configuration: MyStreamServerConfiguration private val configuration: MyStreamServerConfiguration
) : Logging, StreamServer<MyStreamServerConfiguration> { ) : StreamServer<MyStreamServerConfiguration> {
protected var server: HttpServer? = null private var server: HttpServer? = null
@Synchronized @Synchronized
@Throws(InitializationException::class) @Throws(InitializationException::class)
override fun init(bindAddress: InetAddress, router: Router) { override fun init(bindAddress: InetAddress, router: Router) {
try { try {
val socketAddress = InetSocketAddress(bindAddress, configuration.getListenPort()) val socketAddress = InetSocketAddress(bindAddress, configuration.listenPort)
server = HttpServer.create(socketAddress, configuration.tcpConnectionBacklog) server = HttpServer.create(socketAddress, configuration.tcpConnectionBacklog)
server!!.createContext("/", MyRequestHttpHandler(router)) server!!.createContext("/", MyRequestHttpHandler(router))
logger.info("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *") logger.info("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *")
@ -78,12 +78,14 @@ class MyStreamServerImpl(
* Logs a warning and returns `true`, we can't access the socket using the awful JDK webserver API. * Logs a warning and returns `true`, we can't access the socket using the awful JDK webserver API.
* Override this method if you know how to do it. * Override this method if you know how to do it.
*/ */
protected fun isConnectionOpen(exchange: HttpExchange?): Boolean { private fun isConnectionOpen(exchange: HttpExchange?): Boolean {
logger.warn("Can't check client connection, socket access impossible on JDK webserver!") logger.warn("Can't check client connection, socket access impossible on JDK webserver!")
return true return true
} }
protected inner class MyHttpServerConnection(protected var exchange: HttpExchange) : Connection { private inner class MyHttpServerConnection(
private val exchange: HttpExchange
) : Connection {
override fun isOpen(): Boolean { override fun isOpen(): Boolean {
return isConnectionOpen(exchange) return isConnectionOpen(exchange)
} }
@ -96,5 +98,7 @@ class MyStreamServerImpl(
return if (exchange.localAddress != null) exchange.localAddress.address else null return if (exchange.localAddress != null) exchange.localAddress.address else null
} }
} }
companion object: KLogging()
} }

View file

@ -1,138 +1,146 @@
package net.schowek.nextclouddlna.dlna.transport package net.schowek.nextclouddlna.dlna.transport
import io.micrometer.common.util.StringUtils import io.micrometer.common.util.StringUtils
import net.schowek.nextclouddlna.util.Logging import mu.KLogging
import org.jupnp.model.message.StreamRequestMessage import org.jupnp.model.message.StreamRequestMessage
import org.jupnp.model.message.StreamResponseMessage import org.jupnp.model.message.StreamResponseMessage
import org.jupnp.model.message.UpnpMessage import org.jupnp.model.message.UpnpMessage
object StreamsLoggerHelper : Logging { class StreamsLoggerHelper {
private const val HTTPSERVER_REQUEST_BEGIN = companion object : KLogging() {
"================================== HTTPSERVER REQUEST BEGIN =====================================" private const val HTTPSERVER_REQUEST_BEGIN =
private const val HTTPSERVER_REQUEST_END = "================================== HTTPSERVER REQUEST BEGIN ====================================="
"================================== HTTPSERVER REQUEST END =======================================" private const val HTTPSERVER_REQUEST_END =
private const val HTTPSERVER_RESPONSE_BEGIN = "================================== HTTPSERVER REQUEST END ======================================="
"================================== HTTPSERVER RESPONSE BEGIN ====================================" private const val HTTPSERVER_RESPONSE_BEGIN =
private const val HTTPSERVER_RESPONSE_END = "================================== HTTPSERVER RESPONSE BEGIN ===================================="
"================================== HTTPSERVER RESPONSE END ======================================" private const val HTTPSERVER_RESPONSE_END =
private const val HTTPCLIENT_REQUEST_BEGIN = "================================== HTTPSERVER RESPONSE END ======================================"
"==================================== HTTPCLIENT REQUEST BEGIN ====================================" private const val HTTPCLIENT_REQUEST_BEGIN =
private const val HTTPCLIENT_REQUEST_END = "==================================== HTTPCLIENT REQUEST BEGIN ===================================="
"==================================== HTTPCLIENT REQUEST END ======================================" private const val HTTPCLIENT_REQUEST_END =
private const val HTTPCLIENT_RESPONSE_BEGIN = "==================================== HTTPCLIENT REQUEST END ======================================"
"==================================== HTTPCLIENT RESPONSE BEGIN ===================================" private const val HTTPCLIENT_RESPONSE_BEGIN =
private const val HTTPCLIENT_RESPONSE_END = "==================================== HTTPCLIENT RESPONSE BEGIN ==================================="
"==================================== HTTPCLIENT RESPONSE END =====================================" private const val HTTPCLIENT_RESPONSE_END =
"==================================== HTTPCLIENT RESPONSE END ====================================="
fun logStreamServerRequestMessage(requestMessage: StreamRequestMessage) { fun logStreamServerRequestMessage(requestMessage: StreamRequestMessage) {
val formattedRequest = getFormattedRequest(requestMessage) val formattedRequest = getFormattedRequest(requestMessage)
val formattedHeaders = getFormattedHeaders(requestMessage) val formattedHeaders = getFormattedHeaders(requestMessage)
val formattedBody = getFormattedBody(requestMessage) val formattedBody = getFormattedBody(requestMessage)
logger.trace( logger.trace(
"Received a request from {}:\n{}\n{}{}{}{}", "Received a request from {}:\n{}\n{}{}{}{}",
requestMessage.connection.remoteAddress.hostAddress, requestMessage.connection.remoteAddress.hostAddress,
HTTPSERVER_REQUEST_BEGIN, HTTPSERVER_REQUEST_BEGIN,
formattedRequest, formattedRequest,
formattedHeaders, formattedHeaders,
formattedBody, formattedBody,
HTTPSERVER_REQUEST_END HTTPSERVER_REQUEST_END
) )
} }
fun logStreamServerResponseMessage(responseMessage: StreamResponseMessage, requestMessage: StreamRequestMessage) { fun logStreamServerResponseMessage(
val formattedResponse = getFormattedResponse(responseMessage) responseMessage: StreamResponseMessage,
val formattedHeaders = getFormattedHeaders(responseMessage) requestMessage: StreamRequestMessage
val formattedBody = getFormattedBody(responseMessage) ) {
logger.trace( val formattedResponse = getFormattedResponse(responseMessage)
"Send a response to {}:\n{}\n{}{}{}{}", val formattedHeaders = getFormattedHeaders(responseMessage)
requestMessage.connection.remoteAddress.hostAddress, val formattedBody = getFormattedBody(responseMessage)
HTTPSERVER_RESPONSE_BEGIN, logger.trace(
formattedResponse, "Send a response to {}:\n{}\n{}{}{}{}",
formattedHeaders, requestMessage.connection.remoteAddress.hostAddress,
formattedBody, HTTPSERVER_RESPONSE_BEGIN,
HTTPSERVER_RESPONSE_END formattedResponse,
) formattedHeaders,
} formattedBody,
HTTPSERVER_RESPONSE_END
)
}
fun logStreamClientRequestMessage(requestMessage: StreamRequestMessage) { fun logStreamClientRequestMessage(requestMessage: StreamRequestMessage) {
val formattedRequest = getFormattedRequest(requestMessage) val formattedRequest = getFormattedRequest(requestMessage)
val formattedHeaders = getFormattedHeaders(requestMessage) val formattedHeaders = getFormattedHeaders(requestMessage)
val formattedBody = getFormattedBody(requestMessage) val formattedBody = getFormattedBody(requestMessage)
logger.trace( logger.trace(
"Send a request to {}:\n{}\n{}{}{}{}", "Send a request to {}:\n{}\n{}{}{}{}",
requestMessage.uri.host, requestMessage.uri.host,
HTTPCLIENT_REQUEST_BEGIN, HTTPCLIENT_REQUEST_BEGIN,
formattedRequest, formattedRequest,
formattedHeaders, formattedHeaders,
formattedBody, formattedBody,
HTTPCLIENT_REQUEST_END HTTPCLIENT_REQUEST_END
) )
} }
fun logStreamClientResponseMessage(responseMessage: StreamResponseMessage, requestMessage: StreamRequestMessage?) { fun logStreamClientResponseMessage(
val formattedResponse = getFormattedResponse(responseMessage) responseMessage: StreamResponseMessage,
val formattedHeaders = getFormattedHeaders(responseMessage) requestMessage: StreamRequestMessage?
val formattedBody = getFormattedBody(responseMessage) ) {
logger.trace( val formattedResponse = getFormattedResponse(responseMessage)
"Received a response from {}:\n{}\n{}{}{}{}", val formattedHeaders = getFormattedHeaders(responseMessage)
requestMessage?.uri?.host, val formattedBody = getFormattedBody(responseMessage)
HTTPCLIENT_RESPONSE_BEGIN, logger.trace(
formattedResponse, "Received a response from {}:\n{}\n{}{}{}{}",
formattedHeaders, requestMessage?.uri?.host,
formattedBody, HTTPCLIENT_RESPONSE_BEGIN,
HTTPCLIENT_RESPONSE_END formattedResponse,
) formattedHeaders,
} formattedBody,
HTTPCLIENT_RESPONSE_END
)
}
private fun getFormattedRequest(requestMessage: StreamRequestMessage): String { private fun getFormattedRequest(requestMessage: StreamRequestMessage): String {
val request = StringBuilder() val request = StringBuilder()
request.append(requestMessage.operation.httpMethodName).append(" ").append(requestMessage.uri.path) request.append(requestMessage.operation.httpMethodName).append(" ").append(requestMessage.uri.path)
request.append(" HTTP/1.").append(requestMessage.operation.httpMinorVersion).append("\n") request.append(" HTTP/1.").append(requestMessage.operation.httpMinorVersion).append("\n")
return request.toString() return request.toString()
} }
private fun getFormattedResponse(responseMessage: StreamResponseMessage): String { private fun getFormattedResponse(responseMessage: StreamResponseMessage): String {
val response = StringBuilder() val response = StringBuilder()
response.append("HTTP/1.").append(responseMessage.operation.httpMinorVersion) response.append("HTTP/1.").append(responseMessage.operation.httpMinorVersion)
response.append(" ").append(responseMessage.operation.responseDetails).append("\n") response.append(" ").append(responseMessage.operation.responseDetails).append("\n")
return response.toString() return response.toString()
} }
private fun getFormattedHeaders(message: UpnpMessage<*>): String { private fun getFormattedHeaders(message: UpnpMessage<*>): String {
val headers = StringBuilder() val headers = StringBuilder()
for ((key, value1) in message.headers) { for ((key, value1) in message.headers) {
if (StringUtils.isNotEmpty(key)) { if (StringUtils.isNotEmpty(key)) {
for (value in value1) { for (value in value1) {
headers.append(" ").append(key).append(": ").append(value).append("\n") headers.append(" ").append(key).append(": ").append(value).append("\n")
}
} }
} }
} if (headers.isNotEmpty()) {
if (headers.isNotEmpty()) { headers.insert(0, "\nHEADER:\n")
headers.insert(0, "\nHEADER:\n")
}
return headers.toString()
}
private fun getFormattedBody(message: UpnpMessage<*>): String {
var formattedBody = ""
//message.isBodyNonEmptyString throw StringIndexOutOfBoundsException if string is empty
try {
val bodyNonEmpty = message.body != null &&
(message.body is String && (message.body as String).isNotEmpty()
|| message.body is ByteArray && (message.body as ByteArray).isNotEmpty())
if (bodyNonEmpty && message.isBodyNonEmptyString) {
formattedBody = message.bodyString
} }
} catch (e: Exception) { return headers.toString()
formattedBody = ""
} }
formattedBody = if (StringUtils.isNotEmpty(formattedBody)) {
"\nCONTENT:\n$formattedBody" private fun getFormattedBody(message: UpnpMessage<*>): String {
} else { var formattedBody = ""
"" //message.isBodyNonEmptyString throw StringIndexOutOfBoundsException if string is empty
try {
val bodyNonEmpty = message.body != null &&
(message.body is String && (message.body as String).isNotEmpty()
|| message.body is ByteArray && (message.body as ByteArray).isNotEmpty())
if (bodyNonEmpty && message.isBodyNonEmptyString) {
formattedBody = message.bodyString
}
} catch (e: Exception) {
formattedBody = ""
}
formattedBody = if (StringUtils.isNotEmpty(formattedBody)) {
"\nCONTENT:\n$formattedBody"
} else {
""
}
return formattedBody
} }
return formattedBody
} }
} }

View file

@ -1,12 +1,12 @@
package net.schowek.nextclouddlna.nextcloud package net.schowek.nextclouddlna.nextcloud
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
import mu.KLogging
import net.schowek.nextclouddlna.nextcloud.content.ContentItem import net.schowek.nextclouddlna.nextcloud.content.ContentItem
import net.schowek.nextclouddlna.nextcloud.content.ContentNode import net.schowek.nextclouddlna.nextcloud.content.ContentNode
import net.schowek.nextclouddlna.nextcloud.content.MediaFormat import net.schowek.nextclouddlna.nextcloud.content.MediaFormat
import net.schowek.nextclouddlna.nextcloud.db.* import net.schowek.nextclouddlna.nextcloud.db.*
import net.schowek.nextclouddlna.nextcloud.db.Filecache.Companion.FOLDER_MIME_TYPE import net.schowek.nextclouddlna.nextcloud.db.Filecache.Companion.FOLDER_MIME_TYPE
import net.schowek.nextclouddlna.util.Logging
import org.springframework.dao.InvalidDataAccessResourceUsageException import org.springframework.dao.InvalidDataAccessResourceUsageException
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
@ -19,7 +19,7 @@ class MediaDB(
private val mimetypeRepository: MimetypeRepository, private val mimetypeRepository: MimetypeRepository,
private val filecacheRepository: FilecacheRepository, private val filecacheRepository: FilecacheRepository,
private val groupFolderRepository: GroupFolderRepository private val groupFolderRepository: GroupFolderRepository
) : Logging { ) {
private val thumbStorageId: Int = filecacheRepository.findFirstByPath(nextcloudConfig.appDataDir).storage private val thumbStorageId: Int = filecacheRepository.findFirstByPath(nextcloudConfig.appDataDir).storage
private val mimetypes: Map<Int, String> = mimetypeRepository.findAll().associate { it.id to it.mimetype } private val mimetypes: Map<Int, String> = mimetypeRepository.findAll().associate { it.id to it.mimetype }
private val folderMimeType: Int = mimetypes.entries.find { it.value == FOLDER_MIME_TYPE }!!.key private val folderMimeType: Int = mimetypes.entries.find { it.value == FOLDER_MIME_TYPE }!!.key
@ -100,5 +100,7 @@ class MediaDB(
nextcloudConfig.appDataDir + "/" + f.path nextcloudConfig.appDataDir + "/" + f.path
} }
} }
companion object: KLogging()
} }

View file

@ -1,8 +1,8 @@
package net.schowek.nextclouddlna.nextcloud package net.schowek.nextclouddlna.nextcloud
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
import mu.KLogging
import net.schowek.nextclouddlna.nextcloud.db.AppConfigRepository import net.schowek.nextclouddlna.nextcloud.db.AppConfigRepository
import net.schowek.nextclouddlna.util.Logging
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import java.io.File import java.io.File
@ -16,7 +16,7 @@ class NextcloudConfigDiscovery(
@Value("\${nextcloud.filesDir}") @Value("\${nextcloud.filesDir}")
val nextcloudDir: String, val nextcloudDir: String,
val appConfigRepository: AppConfigRepository val appConfigRepository: AppConfigRepository
) : Logging { ) {
final val appDataDir: String = findAppDataDir() final val appDataDir: String = findAppDataDir()
final val supportsGroupFolders: Boolean = checkGroupFoldersSupport() final val supportsGroupFolders: Boolean = checkGroupFoldersSupport()
@ -35,7 +35,7 @@ class NextcloudConfigDiscovery(
})).findFirst().orElseThrow().name })).findFirst().orElseThrow().name
} }
companion object { companion object : KLogging() {
const val APPDATA_NAME_PATTERN = "appdata_\\w+" const val APPDATA_NAME_PATTERN = "appdata_\\w+"
} }
} }

View file

@ -1,8 +1,8 @@
package net.schowek.nextclouddlna.nextcloud.content package net.schowek.nextclouddlna.nextcloud.content
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
import mu.KLogging
import net.schowek.nextclouddlna.nextcloud.MediaDB import net.schowek.nextclouddlna.nextcloud.MediaDB
import net.schowek.nextclouddlna.util.Logging
import org.springframework.scheduling.annotation.Scheduled import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@ -12,7 +12,7 @@ import java.util.regex.Pattern
@Component @Component
class ContentTreeProvider( class ContentTreeProvider(
private val mediaDB: MediaDB private val mediaDB: MediaDB
) : Logging { ) {
private var tree = buildContentTree() private var tree = buildContentTree()
private var lastMTime = 0L private var lastMTime = 0L
@ -91,6 +91,8 @@ class ContentTreeProvider(
fun getItem(id: String): ContentItem? = tree.getItem(id) fun getItem(id: String): ContentItem? = tree.getItem(id)
fun getNode(id: String): ContentNode? = tree.getNode(id) fun getNode(id: String): ContentNode? = tree.getNode(id)
companion object : KLogging()
} }

View file

@ -1,14 +0,0 @@
package net.schowek.nextclouddlna.util
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import kotlin.reflect.KClass
interface Logging {
val logger: Logger
get() = LoggerFactory.getLogger(classNameOf(this::class))
}
fun classNameOf(ownerClass: KClass<*>): String =
if (ownerClass.isCompanion) ownerClass.java.enclosingClass.name else ownerClass.java.name

View file

@ -1,6 +1,7 @@
package net.schowek.nextclouddlna.util package net.schowek.nextclouddlna.util
import jakarta.annotation.PostConstruct import jakarta.annotation.PostConstruct
import mu.KLogging
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import java.net.* import java.net.*
@ -10,7 +11,7 @@ import java.util.*
class ServerInfoProvider( class ServerInfoProvider(
@param:Value("\${server.port}") val port: Int, @param:Value("\${server.port}") val port: Int,
@param:Value("\${server.interface}") private val networkInterface: String @param:Value("\${server.interface}") private val networkInterface: String
) : Logging { ) {
var address: InetAddress? = null var address: InetAddress? = null
@PostConstruct @PostConstruct
@ -35,4 +36,6 @@ class ServerInfoProvider(
throw RuntimeException(e) throw RuntimeException(e)
} }
} }
companion object : KLogging()
} }