Fix multiple constructors with @Inject annotation
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / core / DefaultElementLoader.kt
1 package net.pterodactylus.sone.core
2
3 import com.google.common.base.Ticker
4 import com.google.common.cache.CacheBuilder
5 import freenet.keys.FreenetURI
6 import java.io.ByteArrayInputStream
7 import java.util.concurrent.TimeUnit.MINUTES
8 import javax.imageio.ImageIO
9 import javax.inject.Inject
10
11 /**
12  * [ElementLoader] implementation that uses a simple Guava [com.google.common.cache.Cache].
13  */
14 class DefaultElementLoader(private val freenetInterface: FreenetInterface, ticker: Ticker) : ElementLoader {
15
16         @Inject constructor(freenetInterface: FreenetInterface) : this(freenetInterface, Ticker.systemTicker())
17
18         private val loadingLinks = CacheBuilder.newBuilder().build<String, Boolean>()
19         private val failureCache = CacheBuilder.newBuilder().ticker(ticker).expireAfterWrite(30, MINUTES).build<String, Boolean>()
20         private val imageCache = CacheBuilder.newBuilder().build<String, LinkedElement>()
21         private val callback = object : FreenetInterface.BackgroundFetchCallback {
22                 override fun cancelForMimeType(uri: FreenetURI, mimeType: String): Boolean {
23                         return !mimeType.startsWith("image/")
24                 }
25
26                 override fun loaded(uri: FreenetURI, mimeType: String, data: ByteArray) {
27                         if (!mimeType.startsWith("image/")) {
28                                 return
29                         }
30                         ByteArrayInputStream(data).use {
31                                 ImageIO.read(it)
32                         }?.let {
33                                 imageCache.get(uri.toString()) { LinkedElement(uri.toString()) }
34                         }
35                         removeLoadingLink(uri)
36                 }
37
38                 override fun failed(uri: FreenetURI) {
39                         failureCache.put(uri.toString(), true)
40                         removeLoadingLink(uri)
41                 }
42
43                 private fun removeLoadingLink(uri: FreenetURI) {
44                         synchronized(loadingLinks) {
45                                 loadingLinks.invalidate(uri.toString())
46                         }
47                 }
48         }
49
50         override fun loadElement(link: String): LinkedElement {
51                 synchronized(loadingLinks) {
52                         imageCache.getIfPresent(link)?.run {
53                                 return this
54                         }
55                         failureCache.getIfPresent(link)?.run {
56                                 return LinkedElement(link, failed = true)
57                         }
58                         if (loadingLinks.getIfPresent(link) == null) {
59                                 loadingLinks.put(link, true)
60                                 freenetInterface.startFetch(FreenetURI(link), callback)
61                         }
62                 }
63                 return LinkedElement(link, loading = true)
64         }
65
66 }