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 'com.fasterxml.jackson.module:jackson-module-kotlin'
|
||||
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.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.HttpServletResponse
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.content.ContentGroup.*
|
||||
import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider
|
||||
import net.schowek.nextclouddlna.nextcloud.content.MediaFormat
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import org.jupnp.support.model.Protocol
|
||||
import org.jupnp.support.model.ProtocolInfo
|
||||
import org.jupnp.support.model.dlna.*
|
||||
|
@ -25,7 +25,7 @@ import java.util.*
|
|||
@RestController
|
||||
class ContentController(
|
||||
private val contentTreeProvider: ContentTreeProvider
|
||||
) : Logging {
|
||||
) {
|
||||
@RequestMapping(method = [RequestMethod.GET, RequestMethod.HEAD], value = ["/c/{id}"])
|
||||
@ResponseBody
|
||||
fun getResource(
|
||||
|
@ -73,5 +73,6 @@ class ContentController(
|
|||
}
|
||||
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<*> {
|
||||
return ApacheStreamClient(
|
||||
ApacheStreamClientConfiguration(syncProtocolExecutorService)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.schowek.nextclouddlna.dlna.media
|
||||
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.content.ContentTreeProvider
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import org.jupnp.support.contentdirectory.AbstractContentDirectoryService
|
||||
import org.jupnp.support.contentdirectory.ContentDirectoryErrorCode
|
||||
import org.jupnp.support.contentdirectory.ContentDirectoryException
|
||||
|
@ -25,7 +25,7 @@ class ContentDirectoryService(
|
|||
) : AbstractContentDirectoryService(
|
||||
mutableListOf("dc:title", "upnp:class"), // also "dc:creator", "dc:date", "res@size"
|
||||
mutableListOf("dc:title")
|
||||
), Logging {
|
||||
) {
|
||||
|
||||
/**
|
||||
* Root is requested with objectID="0".
|
||||
|
@ -77,7 +77,7 @@ class ContentDirectoryService(
|
|||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : KLogging() {
|
||||
@Throws(Exception::class)
|
||||
private fun toRangedResult(
|
||||
containers: List<Container>,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.schowek.nextclouddlna.dlna.media
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.util.ExternalUrls
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import org.jupnp.model.meta.*
|
||||
import org.jupnp.model.types.UDADeviceType
|
||||
import org.jupnp.model.types.UDN.uniqueSystemIdentifier
|
||||
|
@ -21,7 +21,7 @@ class MediaServer(
|
|||
@Value("\${server.friendlyName}")
|
||||
private val friendlyName: String,
|
||||
private val externalUrls: ExternalUrls
|
||||
) : Logging {
|
||||
) {
|
||||
val device = LocalDevice(
|
||||
DeviceIdentity(uniqueSystemIdentifier("DLNAtoad-MediaServer"), 300),
|
||||
UDADeviceType(DEVICE_TYPE, VERSION),
|
||||
|
@ -34,7 +34,7 @@ class MediaServer(
|
|||
logger.info("uniqueSystemIdentifier: {} ({})", device.identity.udn, friendlyName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : KLogging() {
|
||||
private const val DEVICE_TYPE = "MediaServer"
|
||||
private const val VERSION = 1
|
||||
const val ICON_FILENAME = "icon.png"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import mu.KLogging
|
||||
import org.apache.http.*
|
||||
import org.apache.http.client.ResponseHandler
|
||||
import org.apache.http.client.config.RequestConfig
|
||||
|
@ -30,7 +30,7 @@ import java.util.concurrent.Callable
|
|||
|
||||
class ApacheStreamClient(
|
||||
private val configuration: ApacheStreamClientConfiguration
|
||||
) : Logging, AbstractStreamClient<ApacheStreamClientConfiguration?, HttpRequestBase>() {
|
||||
) : AbstractStreamClient<ApacheStreamClientConfiguration?, HttpRequestBase>() {
|
||||
private val clientConnectionManager: PoolingHttpClientConnectionManager
|
||||
private val httpClient: CloseableHttpClient
|
||||
|
||||
|
@ -230,7 +230,7 @@ class ApacheStreamClient(
|
|||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : KLogging() {
|
||||
private fun addHeaders(httpMessage: HttpMessage, headers: Headers) {
|
||||
for ((key, value1) in headers) {
|
||||
for (value in value1) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import mu.KLogging
|
||||
import org.jupnp.model.message.*
|
||||
import org.jupnp.protocol.ProtocolFactory
|
||||
import org.jupnp.transport.spi.UpnpStream
|
||||
|
@ -13,38 +13,34 @@ import java.net.HttpURLConnection
|
|||
|
||||
|
||||
abstract class MyHttpExchangeUpnpStream(
|
||||
protocolFactory: ProtocolFactory?,
|
||||
val httpExchange: HttpExchange
|
||||
) : Logging, UpnpStream(protocolFactory) {
|
||||
protocolFactory: ProtocolFactory,
|
||||
private val httpExchange: HttpExchange
|
||||
) : UpnpStream(protocolFactory) {
|
||||
|
||||
override fun run() {
|
||||
try {
|
||||
val xchng = httpExchange
|
||||
|
||||
// Status
|
||||
val requestMessage = StreamRequestMessage(
|
||||
UpnpRequest.Method.getByHttpName(xchng.requestMethod),
|
||||
xchng.requestURI
|
||||
UpnpRequest.Method.getByHttpName(httpExchange.requestMethod),
|
||||
httpExchange.requestURI
|
||||
)
|
||||
if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) {
|
||||
logger.warn("Method not supported by UPnP stack: {}", xchng.requestMethod)
|
||||
throw RuntimeException("Method not supported: {}" + xchng.requestMethod)
|
||||
logger.warn("Method not supported by UPnP stack: {}", httpExchange.requestMethod)
|
||||
throw RuntimeException("Method not supported: {}" + httpExchange.requestMethod)
|
||||
}
|
||||
|
||||
// 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
|
||||
requestMessage.connection = createConnection()
|
||||
|
||||
// Headers
|
||||
requestMessage.headers = UpnpHeaders(xchng.requestHeaders)
|
||||
requestMessage.headers = UpnpHeaders(httpExchange.requestHeaders)
|
||||
|
||||
// Body
|
||||
val bodyBytes: ByteArray
|
||||
var inputStream: InputStream? = null
|
||||
try {
|
||||
inputStream = xchng.requestBody
|
||||
inputStream = httpExchange.requestBody
|
||||
bodyBytes = IO.readBytes(inputStream)
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
|
@ -67,13 +63,13 @@ abstract class MyHttpExchangeUpnpStream(
|
|||
// Return the response
|
||||
if (responseMessage != null) {
|
||||
// Headers
|
||||
xchng.responseHeaders.putAll(responseMessage.headers)
|
||||
httpExchange.responseHeaders.putAll(responseMessage.headers)
|
||||
|
||||
// Body
|
||||
val responseBodyBytes = if (responseMessage.hasBody()) responseMessage.bodyBytes else null
|
||||
val contentLength = responseBodyBytes?.size ?: -1
|
||||
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()) {
|
||||
logger.debug(" Response body: " + responseMessage.body)
|
||||
}
|
||||
|
@ -81,7 +77,7 @@ abstract class MyHttpExchangeUpnpStream(
|
|||
logger.debug("Response message has body, writing bytes to stream...")
|
||||
var outputStream: OutputStream? = null
|
||||
try {
|
||||
outputStream = xchng.responseBody
|
||||
outputStream = httpExchange.responseBody
|
||||
IO.writeBytes(outputStream, responseBodyBytes)
|
||||
outputStream.flush()
|
||||
} finally {
|
||||
|
@ -91,11 +87,10 @@ abstract class MyHttpExchangeUpnpStream(
|
|||
} else {
|
||||
// If it's null, it's 404, everything else needs a proper httpResponse
|
||||
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)
|
||||
} catch (t: Throwable) {
|
||||
|
||||
// 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.
|
||||
// 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?
|
||||
|
||||
companion object: KLogging()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import org.jupnp.transport.spi.StreamServerConfiguration
|
|||
class MyStreamServerConfiguration(
|
||||
private val listenPort: Int
|
||||
) : StreamServerConfiguration {
|
||||
var tcpConnectionBacklog = 0
|
||||
val tcpConnectionBacklog = 0
|
||||
override fun getListenPort(): Int {
|
||||
return listenPort
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package net.schowek.nextclouddlna.dlna.transport
|
|||
import com.sun.net.httpserver.HttpExchange
|
||||
import com.sun.net.httpserver.HttpHandler
|
||||
import com.sun.net.httpserver.HttpServer
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import mu.KLogging
|
||||
import org.jupnp.model.message.Connection
|
||||
import org.jupnp.transport.Router
|
||||
import org.jupnp.transport.spi.InitializationException
|
||||
|
@ -15,14 +15,14 @@ import java.net.InetSocketAddress
|
|||
|
||||
class MyStreamServerImpl(
|
||||
private val configuration: MyStreamServerConfiguration
|
||||
) : Logging, StreamServer<MyStreamServerConfiguration> {
|
||||
protected var server: HttpServer? = null
|
||||
) : StreamServer<MyStreamServerConfiguration> {
|
||||
private var server: HttpServer? = null
|
||||
|
||||
@Synchronized
|
||||
@Throws(InitializationException::class)
|
||||
override fun init(bindAddress: InetAddress, router: Router) {
|
||||
try {
|
||||
val socketAddress = InetSocketAddress(bindAddress, configuration.getListenPort())
|
||||
val socketAddress = InetSocketAddress(bindAddress, configuration.listenPort)
|
||||
server = HttpServer.create(socketAddress, configuration.tcpConnectionBacklog)
|
||||
server!!.createContext("/", MyRequestHttpHandler(router))
|
||||
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.
|
||||
* 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!")
|
||||
return true
|
||||
}
|
||||
|
||||
protected inner class MyHttpServerConnection(protected var exchange: HttpExchange) : Connection {
|
||||
private inner class MyHttpServerConnection(
|
||||
private val exchange: HttpExchange
|
||||
) : Connection {
|
||||
override fun isOpen(): Boolean {
|
||||
return isConnectionOpen(exchange)
|
||||
}
|
||||
|
@ -96,5 +98,7 @@ class MyStreamServerImpl(
|
|||
return if (exchange.localAddress != null) exchange.localAddress.address else null
|
||||
}
|
||||
}
|
||||
|
||||
companion object: KLogging()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
|
||||
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.StreamResponseMessage
|
||||
import org.jupnp.model.message.UpnpMessage
|
||||
|
||||
|
||||
object StreamsLoggerHelper : Logging {
|
||||
class StreamsLoggerHelper {
|
||||
companion object : KLogging() {
|
||||
private const val HTTPSERVER_REQUEST_BEGIN =
|
||||
"================================== HTTPSERVER REQUEST BEGIN ====================================="
|
||||
private const val HTTPSERVER_REQUEST_END =
|
||||
|
@ -40,7 +41,10 @@ object StreamsLoggerHelper : Logging {
|
|||
)
|
||||
}
|
||||
|
||||
fun logStreamServerResponseMessage(responseMessage: StreamResponseMessage, requestMessage: StreamRequestMessage) {
|
||||
fun logStreamServerResponseMessage(
|
||||
responseMessage: StreamResponseMessage,
|
||||
requestMessage: StreamRequestMessage
|
||||
) {
|
||||
val formattedResponse = getFormattedResponse(responseMessage)
|
||||
val formattedHeaders = getFormattedHeaders(responseMessage)
|
||||
val formattedBody = getFormattedBody(responseMessage)
|
||||
|
@ -70,7 +74,10 @@ object StreamsLoggerHelper : Logging {
|
|||
)
|
||||
}
|
||||
|
||||
fun logStreamClientResponseMessage(responseMessage: StreamResponseMessage, requestMessage: StreamRequestMessage?) {
|
||||
fun logStreamClientResponseMessage(
|
||||
responseMessage: StreamResponseMessage,
|
||||
requestMessage: StreamRequestMessage?
|
||||
) {
|
||||
val formattedResponse = getFormattedResponse(responseMessage)
|
||||
val formattedHeaders = getFormattedHeaders(responseMessage)
|
||||
val formattedBody = getFormattedBody(responseMessage)
|
||||
|
@ -135,4 +142,5 @@ object StreamsLoggerHelper : Logging {
|
|||
return formattedBody
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package net.schowek.nextclouddlna.nextcloud
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.content.ContentItem
|
||||
import net.schowek.nextclouddlna.nextcloud.content.ContentNode
|
||||
import net.schowek.nextclouddlna.nextcloud.content.MediaFormat
|
||||
import net.schowek.nextclouddlna.nextcloud.db.*
|
||||
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.stereotype.Component
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
@ -19,7 +19,7 @@ class MediaDB(
|
|||
private val mimetypeRepository: MimetypeRepository,
|
||||
private val filecacheRepository: FilecacheRepository,
|
||||
private val groupFolderRepository: GroupFolderRepository
|
||||
) : Logging {
|
||||
) {
|
||||
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 folderMimeType: Int = mimetypes.entries.find { it.value == FOLDER_MIME_TYPE }!!.key
|
||||
|
@ -100,5 +100,7 @@ class MediaDB(
|
|||
nextcloudConfig.appDataDir + "/" + f.path
|
||||
}
|
||||
}
|
||||
|
||||
companion object: KLogging()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.schowek.nextclouddlna.nextcloud
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.db.AppConfigRepository
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.File
|
||||
|
@ -16,7 +16,7 @@ class NextcloudConfigDiscovery(
|
|||
@Value("\${nextcloud.filesDir}")
|
||||
val nextcloudDir: String,
|
||||
val appConfigRepository: AppConfigRepository
|
||||
) : Logging {
|
||||
) {
|
||||
final val appDataDir: String = findAppDataDir()
|
||||
final val supportsGroupFolders: Boolean = checkGroupFoldersSupport()
|
||||
|
||||
|
@ -35,7 +35,7 @@ class NextcloudConfigDiscovery(
|
|||
})).findFirst().orElseThrow().name
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : KLogging() {
|
||||
const val APPDATA_NAME_PATTERN = "appdata_\\w+"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.schowek.nextclouddlna.nextcloud.content
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.MediaDB
|
||||
import net.schowek.nextclouddlna.util.Logging
|
||||
import org.springframework.scheduling.annotation.Scheduled
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
@ -12,7 +12,7 @@ import java.util.regex.Pattern
|
|||
@Component
|
||||
class ContentTreeProvider(
|
||||
private val mediaDB: MediaDB
|
||||
) : Logging {
|
||||
) {
|
||||
private var tree = buildContentTree()
|
||||
private var lastMTime = 0L
|
||||
|
||||
|
@ -91,6 +91,8 @@ class ContentTreeProvider(
|
|||
|
||||
fun getItem(id: String): ContentItem? = tree.getItem(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
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Component
|
||||
import java.net.*
|
||||
|
@ -10,7 +11,7 @@ import java.util.*
|
|||
class ServerInfoProvider(
|
||||
@param:Value("\${server.port}") val port: Int,
|
||||
@param:Value("\${server.interface}") private val networkInterface: String
|
||||
) : Logging {
|
||||
) {
|
||||
var address: InetAddress? = null
|
||||
|
||||
@PostConstruct
|
||||
|
@ -35,4 +36,6 @@ class ServerInfoProvider(
|
|||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
companion object : KLogging()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue