Kotlin logging
This commit is contained in:
parent
4da6b541d8
commit
4e8ddbb5bf
15 changed files with 180 additions and 176 deletions
|
@ -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'
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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+"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue