Merge remote-tracking branch 'origin/upnpservice_as_bean' into dev
This commit is contained in:
commit
615b488a49
22 changed files with 249 additions and 119 deletions
|
@ -46,6 +46,7 @@ dependencies {
|
|||
|
||||
implementation 'org.jupnp:org.jupnp:2.7.1'
|
||||
implementation 'org.jupnp:org.jupnp.support:2.7.1'
|
||||
implementation 'org.osgi:org.osgi.service.http:1.2.2'
|
||||
implementation 'org.apache.httpcomponents:httpclient:4.5.14'
|
||||
// to avoid snakeyaml-1.3 vulnerability CVE-2022-1471
|
||||
implementation 'org.yaml:snakeyaml:2.2'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.schowek.nextclouddlna.controller
|
||||
|
||||
|
||||
import net.schowek.nextclouddlna.dlna.media.MediaServer
|
||||
import net.schowek.nextclouddlna.dlna.DlnaService
|
||||
import net.schowek.nextclouddlna.dlna.MediaServer
|
||||
import org.jupnp.support.model.DIDLObject
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.http.HttpStatus
|
||||
|
@ -14,11 +14,14 @@ class UpnpControllerIntTest extends UpnpAwareSpecification {
|
|||
|
||||
@Autowired
|
||||
private MediaServer mediaServer
|
||||
@Autowired
|
||||
private DlnaService dlnaService
|
||||
|
||||
def uid
|
||||
|
||||
def setup() {
|
||||
uid = mediaServer.serviceIdentifier
|
||||
dlnaService.start()
|
||||
}
|
||||
|
||||
def "should serve icon"() {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package net.schowek.nextclouddlna.dlna
|
||||
|
||||
import org.jupnp.UpnpService
|
||||
import org.jupnp.model.message.discovery.OutgoingSearchRequest
|
||||
import org.jupnp.model.message.header.HostHeader
|
||||
import org.jupnp.model.message.header.MANHeader
|
||||
import org.jupnp.model.message.header.STAllHeader
|
||||
import org.jupnp.model.message.header.UpnpHeader
|
||||
import org.jupnp.model.types.HostPort
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import support.IntegrationSpecification
|
||||
import support.beans.dlna.upnp.UpnpServiceConfigurationInt
|
||||
|
||||
import static org.jupnp.model.Constants.IPV4_UPNP_MULTICAST_GROUP
|
||||
import static org.jupnp.model.Constants.UPNP_MULTICAST_PORT
|
||||
import static org.jupnp.model.message.UpnpRequest.Method.MSEARCH
|
||||
import static org.jupnp.model.message.header.UpnpHeader.Type.*
|
||||
import static org.jupnp.model.types.NotificationSubtype.ALL
|
||||
import static org.jupnp.model.types.NotificationSubtype.DISCOVER
|
||||
|
||||
class DlnaServiceIntTest extends IntegrationSpecification {
|
||||
@Autowired
|
||||
private UpnpService upnpService
|
||||
@Autowired
|
||||
private MediaServer mediaServer
|
||||
|
||||
def "should send initial multicast Upnp datagrams on start"() {
|
||||
given:
|
||||
def configuration = upnpService.configuration as UpnpServiceConfigurationInt
|
||||
def sut = new DlnaService(upnpService, mediaServer)
|
||||
|
||||
expect:
|
||||
configuration.outgoingDatagramMessages == []
|
||||
|
||||
when:
|
||||
sut.start()
|
||||
|
||||
then:
|
||||
configuration.outgoingDatagramMessages.any()
|
||||
configuration.outgoingDatagramMessages[0].class == OutgoingSearchRequest
|
||||
with(configuration.outgoingDatagramMessages[0] as OutgoingSearchRequest) {
|
||||
assert it.operation.method == MSEARCH
|
||||
assert it.destinationAddress == InetAddress.getByName(IPV4_UPNP_MULTICAST_GROUP)
|
||||
assert it.destinationPort == UPNP_MULTICAST_PORT
|
||||
|
||||
assert header(it, MAN, MANHeader.class) == DISCOVER.headerString
|
||||
assert header(it, ST, STAllHeader.class).headerString == ALL.headerString
|
||||
assert header(it, HOST, HostHeader.class) == new HostPort(IPV4_UPNP_MULTICAST_GROUP, UPNP_MULTICAST_PORT)
|
||||
}
|
||||
}
|
||||
|
||||
def <T> T header(OutgoingSearchRequest request, UpnpHeader.Type type, Class<? extends UpnpHeader<T>> clazz) {
|
||||
return clazz.cast(request.headers.get(type).find()).value
|
||||
}
|
||||
}
|
|
@ -6,15 +6,21 @@ import org.springframework.beans.factory.annotation.Autowired
|
|||
import org.springframework.boot.test.context.SpringBootContextLoader
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.annotation.DirtiesContext
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import spock.lang.Specification
|
||||
import support.beans.TestConfig
|
||||
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT
|
||||
import static org.springframework.test.annotation.DirtiesContext.ClassMode.*
|
||||
|
||||
@ContextConfiguration(loader = SpringBootContextLoader, classes = NextcloudDLNAApp.class)
|
||||
@SpringBootTest(webEnvironment = DEFINED_PORT)
|
||||
@ActiveProfiles("integration")
|
||||
@Import(TestConfig.class)
|
||||
@DirtiesContext(classMode = AFTER_CLASS)
|
||||
class IntegrationSpecification extends Specification {
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate
|
||||
|
@ -27,6 +33,6 @@ class IntegrationSpecification extends Specification {
|
|||
private ServerInfoProvider serverInfoProvider
|
||||
|
||||
protected String urlWithPort(String uri = "") {
|
||||
return "http://localhost:" + serverInfoProvider.port + uri;
|
||||
return "http://" + serverInfoProvider.host + ":" + serverInfoProvider.port + uri;
|
||||
}
|
||||
}
|
||||
|
|
7
src/integration/groovy/support/beans/TestConfig.groovy
Normal file
7
src/integration/groovy/support/beans/TestConfig.groovy
Normal file
|
@ -0,0 +1,7 @@
|
|||
package support.beans
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan
|
||||
|
||||
@ComponentScan(["support", "net.schowek.nextclouddlna"])
|
||||
class TestConfig {
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package support.beans.dlna.upnp
|
||||
|
||||
import org.jupnp.DefaultUpnpServiceConfiguration
|
||||
import org.jupnp.model.message.OutgoingDatagramMessage
|
||||
import org.jupnp.transport.impl.DatagramIOConfigurationImpl
|
||||
import org.jupnp.transport.impl.DatagramIOImpl
|
||||
import org.jupnp.transport.spi.DatagramIO
|
||||
import org.jupnp.transport.spi.NetworkAddressFactory
|
||||
import org.jupnp.transport.spi.StreamClient
|
||||
import org.jupnp.transport.spi.StreamServer
|
||||
import org.springframework.context.annotation.Profile
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
@Profile("integration")
|
||||
class UpnpServiceConfigurationInt extends DefaultUpnpServiceConfiguration {
|
||||
List<OutgoingDatagramMessage> outgoingDatagramMessages = new ArrayList<>()
|
||||
|
||||
@Override
|
||||
public StreamClient createStreamClient() {
|
||||
return null
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory) {
|
||||
return null
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramIO createDatagramIO(NetworkAddressFactory networkAddressFactory) {
|
||||
return new MockDatagramIO(this, new DatagramIOConfigurationImpl())
|
||||
}
|
||||
|
||||
private void onOutgoingDatagramMessage(OutgoingDatagramMessage message) {
|
||||
outgoingDatagramMessages.add(message)
|
||||
}
|
||||
|
||||
class MockDatagramIO extends DatagramIOImpl {
|
||||
private final UpnpServiceConfigurationInt upnpServiceConfiguration
|
||||
|
||||
MockDatagramIO(UpnpServiceConfigurationInt upnpServiceConfiguration, DatagramIOConfigurationImpl configuration) {
|
||||
super(configuration)
|
||||
this.upnpServiceConfiguration = upnpServiceConfiguration
|
||||
}
|
||||
|
||||
@Override
|
||||
void send(OutgoingDatagramMessage message) {
|
||||
upnpServiceConfiguration.onOutgoingDatagramMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package net.schowek.nextclouddlna.nextcloud.config
|
||||
|
||||
package support.beans.nextcloud.config
|
||||
|
||||
import net.schowek.nextclouddlna.nextcloud.config.NextcloudAppPathProvider
|
||||
import org.springframework.context.annotation.Profile
|
||||
import org.springframework.stereotype.Component
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package net.schowek.nextclouddlna.util
|
||||
package support.beans.util
|
||||
|
||||
import net.schowek.nextclouddlna.util.ServerInfoProvider
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Profile
|
||||
import org.springframework.stereotype.Component
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.util
|
||||
package support.beans.util
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.boot.web.server.ConfigurableWebServerFactory
|
|
@ -1,90 +0,0 @@
|
|||
package net.schowek.nextclouddlna
|
||||
|
||||
import jakarta.annotation.PreDestroy
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.dlna.media.MediaServer
|
||||
import net.schowek.nextclouddlna.dlna.transport.ApacheStreamClient
|
||||
import net.schowek.nextclouddlna.dlna.transport.ApacheStreamClientConfiguration
|
||||
import net.schowek.nextclouddlna.dlna.transport.MyStreamServerConfiguration
|
||||
import net.schowek.nextclouddlna.dlna.transport.MyStreamServerImpl
|
||||
import net.schowek.nextclouddlna.util.ServerInfoProvider
|
||||
import org.jupnp.DefaultUpnpServiceConfiguration
|
||||
import org.jupnp.UpnpServiceConfiguration
|
||||
import org.jupnp.UpnpServiceImpl
|
||||
import org.jupnp.model.message.StreamRequestMessage
|
||||
import org.jupnp.model.message.StreamResponseMessage
|
||||
import org.jupnp.model.message.UpnpResponse
|
||||
import org.jupnp.protocol.ProtocolFactory
|
||||
import org.jupnp.registry.RegistryImpl
|
||||
import org.jupnp.transport.impl.NetworkAddressFactoryImpl
|
||||
import org.jupnp.transport.spi.NetworkAddressFactory
|
||||
import org.springframework.context.event.ContextRefreshedEvent
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.stereotype.Component
|
||||
import java.net.InetAddress
|
||||
import java.net.NetworkInterface
|
||||
|
||||
|
||||
@Component
|
||||
class DlnaService(
|
||||
private val mediaServer: MediaServer,
|
||||
private val serverInfoProvider: ServerInfoProvider,
|
||||
) {
|
||||
private val addressesToBind: List<String> = listOf(serverInfoProvider.host)
|
||||
var upnpService = MyUpnpService(MyUpnpServiceConfiguration())
|
||||
|
||||
fun start() {
|
||||
upnpService.startup()
|
||||
upnpService.registry.addDevice(mediaServer.device)
|
||||
}
|
||||
|
||||
@EventListener
|
||||
fun handleContextRefresh(event: ContextRefreshedEvent) {
|
||||
start()
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
fun destroy() {
|
||||
upnpService.shutdown()
|
||||
}
|
||||
|
||||
fun processRequest(requestMsg: StreamRequestMessage): StreamResponseMessage {
|
||||
logger.debug { "Processing $requestMsg" }
|
||||
return with(upnpService.protocolFactory.createReceivingSync(requestMsg)) {
|
||||
run()
|
||||
outputMessage
|
||||
?: StreamResponseMessage(UpnpResponse.Status.NOT_FOUND).also {
|
||||
logger.warn { "Could not get response for ${requestMsg.operation.method} ${requestMsg}" }
|
||||
}
|
||||
}.also {
|
||||
logger.debug { "Response: ${it.operation.statusCode} ${it.body}" }
|
||||
}
|
||||
}
|
||||
|
||||
inner class MyUpnpService(
|
||||
configuration: UpnpServiceConfiguration
|
||||
) : UpnpServiceImpl(configuration) {
|
||||
override fun createRegistry(pf: ProtocolFactory) = RegistryImpl(this)
|
||||
}
|
||||
|
||||
private inner class MyUpnpServiceConfiguration : DefaultUpnpServiceConfiguration(serverInfoProvider.port) {
|
||||
override fun createStreamClient() =
|
||||
ApacheStreamClient(ApacheStreamClientConfiguration(syncProtocolExecutorService))
|
||||
|
||||
override fun createStreamServer(networkAddressFactory: NetworkAddressFactory) =
|
||||
MyStreamServerImpl(MyStreamServerConfiguration(networkAddressFactory.streamListenPort))
|
||||
|
||||
override fun createNetworkAddressFactory(streamListenPort: Int, multicastResponsePort: Int) =
|
||||
MyNetworkAddressFactory(streamListenPort, multicastResponsePort)
|
||||
}
|
||||
|
||||
inner class MyNetworkAddressFactory(
|
||||
streamListenPort: Int,
|
||||
multicastResponsePort: Int
|
||||
) : NetworkAddressFactoryImpl(streamListenPort, multicastResponsePort) {
|
||||
override fun isUsableAddress(iface: NetworkInterface, address: InetAddress) =
|
||||
addressesToBind.contains(address.hostAddress)
|
||||
}
|
||||
|
||||
companion object : KLogging()
|
||||
}
|
|
@ -2,9 +2,9 @@ package net.schowek.nextclouddlna.controller
|
|||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.DlnaService
|
||||
import net.schowek.nextclouddlna.dlna.DlnaService
|
||||
import net.schowek.nextclouddlna.dlna.StreamMessageMapper
|
||||
import net.schowek.nextclouddlna.dlna.media.MediaServer
|
||||
import net.schowek.nextclouddlna.dlna.MediaServer
|
||||
import org.springframework.core.io.InputStreamResource
|
||||
import org.springframework.core.io.Resource
|
||||
import org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package net.schowek.nextclouddlna.dlna
|
||||
|
||||
import jakarta.annotation.PreDestroy
|
||||
import mu.KLogging
|
||||
import org.jupnp.UpnpService
|
||||
import org.jupnp.model.message.StreamRequestMessage
|
||||
import org.jupnp.model.message.StreamResponseMessage
|
||||
import org.jupnp.model.message.UpnpResponse
|
||||
import org.springframework.context.event.ContextRefreshedEvent
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
||||
@Component
|
||||
class DlnaService(
|
||||
private val upnpService: UpnpService,
|
||||
private val mediaServer: MediaServer
|
||||
) {
|
||||
fun start() {
|
||||
upnpService.startup()
|
||||
upnpService.registry.addDevice(mediaServer.device)
|
||||
}
|
||||
|
||||
@EventListener(condition = "!@environment.acceptsProfiles('integration')")
|
||||
fun handleContextRefresh(event: ContextRefreshedEvent) {
|
||||
start()
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
fun destroy() {
|
||||
upnpService.shutdown()
|
||||
}
|
||||
|
||||
fun processRequest(requestMsg: StreamRequestMessage): StreamResponseMessage {
|
||||
logger.debug { "Processing $requestMsg" }
|
||||
return with(upnpService.protocolFactory.createReceivingSync(requestMsg)) {
|
||||
run()
|
||||
outputMessage
|
||||
?: StreamResponseMessage(UpnpResponse.Status.NOT_FOUND).also {
|
||||
logger.warn { "Could not get response for ${requestMsg.operation.method} ${requestMsg}" }
|
||||
}
|
||||
}.also {
|
||||
logger.debug { "Response: ${it.operation.statusCode} ${it.body}" }
|
||||
}
|
||||
}
|
||||
|
||||
companion object : KLogging()
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.dlna.media
|
||||
package net.schowek.nextclouddlna.dlna
|
||||
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.util.ExternalUrls
|
|
@ -0,0 +1,10 @@
|
|||
package net.schowek.nextclouddlna.dlna.upnp
|
||||
|
||||
import org.jupnp.UpnpServiceConfiguration
|
||||
import org.jupnp.UpnpServiceImpl
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class MyUpnpService(
|
||||
upnpServiceConfiguration: UpnpServiceConfiguration
|
||||
) : UpnpServiceImpl(upnpServiceConfiguration)
|
|
@ -0,0 +1,44 @@
|
|||
package net.schowek.nextclouddlna.dlna.upnp
|
||||
|
||||
import net.schowek.nextclouddlna.dlna.upnp.transport.ApacheStreamClient
|
||||
import net.schowek.nextclouddlna.dlna.upnp.transport.ApacheStreamClientConfiguration
|
||||
import net.schowek.nextclouddlna.dlna.upnp.transport.MyStreamServerConfiguration
|
||||
import net.schowek.nextclouddlna.dlna.upnp.transport.MyStreamServerImpl
|
||||
import net.schowek.nextclouddlna.util.ServerInfoProvider
|
||||
import org.jupnp.DefaultUpnpServiceConfiguration
|
||||
import org.jupnp.transport.impl.NetworkAddressFactoryImpl
|
||||
import org.jupnp.transport.spi.DatagramIO
|
||||
import org.jupnp.transport.spi.NetworkAddressFactory
|
||||
import org.springframework.context.annotation.Profile
|
||||
import org.springframework.stereotype.Component
|
||||
import java.net.InetAddress
|
||||
import java.net.NetworkInterface
|
||||
|
||||
@Component
|
||||
@Profile("!integration")
|
||||
class MyUpnpServiceConfiguration(
|
||||
private val serverInfoProvider: ServerInfoProvider
|
||||
) : DefaultUpnpServiceConfiguration(serverInfoProvider.port) {
|
||||
val addressesToBind = listOf(serverInfoProvider.host)
|
||||
|
||||
override fun createStreamClient() =
|
||||
ApacheStreamClient(ApacheStreamClientConfiguration(syncProtocolExecutorService))
|
||||
|
||||
override fun createStreamServer(networkAddressFactory: NetworkAddressFactory) =
|
||||
MyStreamServerImpl(MyStreamServerConfiguration(networkAddressFactory.streamListenPort))
|
||||
|
||||
override fun createDatagramIO(networkAddressFactory: NetworkAddressFactory): DatagramIO<*> {
|
||||
return super.createDatagramIO(networkAddressFactory)
|
||||
}
|
||||
|
||||
override fun createNetworkAddressFactory(streamListenPort: Int, multicastResponsePort: Int) =
|
||||
MyNetworkAddressFactory(streamListenPort, multicastResponsePort)
|
||||
|
||||
inner class MyNetworkAddressFactory(
|
||||
streamListenPort: Int,
|
||||
multicastResponsePort: Int
|
||||
) : NetworkAddressFactoryImpl(streamListenPort, multicastResponsePort) {
|
||||
override fun isUsableAddress(iface: NetworkInterface, address: InetAddress) =
|
||||
addressesToBind.contains(address.hostAddress)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
package net.schowek.nextclouddlna.dlna.upnp.transport
|
||||
|
||||
import mu.KLogging
|
||||
import org.apache.http.HttpMessage
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
package net.schowek.nextclouddlna.dlna.upnp.transport
|
||||
|
||||
import org.jupnp.transport.spi.AbstractStreamClientConfiguration
|
||||
import java.util.concurrent.ExecutorService
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
package net.schowek.nextclouddlna.dlna.upnp.transport
|
||||
|
||||
import org.jupnp.transport.spi.StreamServerConfiguration
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.dlna.transport
|
||||
package net.schowek.nextclouddlna.dlna.upnp.transport
|
||||
|
||||
import mu.KLogging
|
||||
import org.jupnp.transport.Router
|
|
@ -1,7 +1,7 @@
|
|||
package net.schowek.nextclouddlna.nextcloud.content
|
||||
|
||||
import mu.KLogging
|
||||
import net.schowek.nextclouddlna.nextcloud.NextcloudDB
|
||||
import net.schowek.nextclouddlna.nextcloud.db.NextcloudDB
|
||||
import org.springframework.scheduling.annotation.Scheduled
|
||||
import org.springframework.stereotype.Component
|
||||
import java.time.Clock
|
||||
|
@ -100,8 +100,8 @@ class ContentTreeProvider(
|
|||
}
|
||||
}
|
||||
|
||||
fun getItem(id: String): ContentItem? = tree.getItem(id)
|
||||
fun getNode(id: String): ContentNode? = tree.getNode(id)
|
||||
fun getItem(id: String) = tree.getItem(id)
|
||||
fun getNode(id: String) = tree.getNode(id)
|
||||
|
||||
companion object : KLogging() {
|
||||
const val REBUILD_TREE_DELAY_IN_MS = 1000 * 60L // 1m
|
||||
|
@ -115,13 +115,11 @@ class ContentTree {
|
|||
private val nodes: MutableMap<String, ContentNode> = HashMap()
|
||||
private val items: MutableMap<String, ContentItem> = HashMap()
|
||||
|
||||
fun getNode(id: String): ContentNode? {
|
||||
return nodes[id]
|
||||
}
|
||||
val itemsCount get() = items.size
|
||||
val nodesCount get() = nodes.size
|
||||
|
||||
fun getItem(id: String): ContentItem? {
|
||||
return items[id]
|
||||
}
|
||||
fun getNode(id: String) = nodes[id]
|
||||
fun getItem(id: String) = items[id]
|
||||
|
||||
fun addItem(item: ContentItem) {
|
||||
items["${item.id}"] = item
|
||||
|
@ -130,8 +128,5 @@ class ContentTree {
|
|||
fun addNode(node: ContentNode) {
|
||||
nodes["${node.id}"] = node
|
||||
}
|
||||
|
||||
val itemsCount get() = items.size
|
||||
val nodesCount get() = nodes.size
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package net.schowek.nextclouddlna.nextcloud
|
||||
package net.schowek.nextclouddlna.nextcloud.db
|
||||
|
||||
import jakarta.annotation.PostConstruct
|
||||
import mu.KLogging
|
||||
|
@ -6,7 +6,6 @@ import net.schowek.nextclouddlna.nextcloud.config.NextcloudConfigDiscovery
|
|||
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 org.springframework.dao.InvalidDataAccessResourceUsageException
|
||||
import org.springframework.stereotype.Component
|
|
@ -1,6 +1,6 @@
|
|||
package net.schowek.nextclouddlna.nextcloud.content
|
||||
|
||||
import net.schowek.nextclouddlna.nextcloud.NextcloudDB
|
||||
import net.schowek.nextclouddlna.nextcloud.db.NextcloudDB
|
||||
import spock.lang.Specification
|
||||
import java.time.Clock
|
||||
import java.time.ZoneId
|
||||
|
|
Loading…
Reference in a new issue