New cache system

Refactoring
Separation into libraries
This commit is contained in:
2021-03-17 19:47:53 +03:00
parent 2004cb7c5e
commit 84d812a6d6
198 changed files with 4892 additions and 3477 deletions
+1
View File
@@ -0,0 +1 @@
/build
+44
View File
@@ -0,0 +1,44 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
View File
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.meloda.netservices">
</manifest>
@@ -0,0 +1,115 @@
package com.meloda.netservices
import androidx.collection.ArrayMap
import com.meloda.netservices.io.EasyStreams
import java.io.IOException
import java.io.InputStream
import java.io.UnsupportedEncodingException
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
class HttpRequest(
private val url: String,
private val method: String,
private val params: ArrayMap<String, String> = ArrayMap<String, String>()
) {
companion object {
const val GET = "GET"
const val POST = "POST"
operator fun get(
url: String,
params: ArrayMap<String, String> = ArrayMap()
): HttpRequest {
return HttpRequest(url, GET, params)
}
operator fun get(url: String): HttpRequest {
return Companion[url, ArrayMap()]
}
}
private var connection: HttpURLConnection? = null
@Throws(IOException::class)
fun asString(): String {
val input = getStream()
val content = EasyStreams.read(input)
connection?.disconnect()
return content
}
@Throws(IOException::class)
fun asBytes(): ByteArray {
val input = getStream()
val content = EasyStreams.readBytes(input)
connection?.disconnect()
return content
}
@Throws(IOException::class)
fun getStream(): InputStream {
if (connection == null) {
connection = createConnection()
}
var input = connection!!.inputStream
val encoding = connection!!.getHeaderField("Content-Encoding")
if ("gzip".equals(encoding, ignoreCase = true)) {
input = EasyStreams.gzip(input)
}
return input
}
@Throws(UnsupportedEncodingException::class)
private fun getParams(): String {
val buffer = StringBuilder()
for (i in 0 until params.size) {
val key = params.keyAt(i)
val value = params.valueAt(i)
buffer.append(key).append("=")
buffer.append(URLEncoder.encode(value, "UTF-8"))
buffer.append("&")
}
return buffer.toString()
}
@Throws(UnsupportedEncodingException::class)
private fun getUrl(): String {
return if (params.isNotEmpty() && "GET".equals(method, ignoreCase = true)) {
url + "?" + getParams()
} else url
}
@Throws(IOException::class)
private fun createConnection(): HttpURLConnection? {
connection = URL(getUrl()).openConnection() as HttpURLConnection
connection!!.readTimeout = 60000
connection!!.connectTimeout = 60000
connection!!.useCaches = true
connection!!.doInput = true
connection!!.doOutput =
!GET.equals(method, ignoreCase = true)
connection!!.requestMethod = method
connection!!.setRequestProperty("Accept-Encoding", "gzip")
return connection
}
override fun toString(): String {
try {
return asString()
} catch (e: IOException) {
e.printStackTrace()
}
return ""
}
}
@@ -0,0 +1,10 @@
package com.meloda.netservices.io
import java.io.ByteArrayOutputStream
class BytesOutputStream : ByteArrayOutputStream {
constructor() : super(8192)
constructor(size: Int) : super(size)
val byteArray: ByteArray = buf
}
@@ -0,0 +1,12 @@
package com.meloda.netservices.io
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
object Charsets {
val ASCII: Charset = StandardCharsets.US_ASCII
val UTF_8: Charset = StandardCharsets.UTF_8
}
@@ -0,0 +1,174 @@
package com.meloda.netservices.io
import org.jetbrains.annotations.Contract
import java.io.*
import java.nio.charset.Charset
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import kotlin.math.max
object EasyStreams {
const val BUFFER_SIZE = 8192
const val CHAR_BUFFER_SIZE = 4096
@JvmOverloads
@Throws(IOException::class)
fun read(from: InputStream, encoding: Charset? = Charsets.UTF_8): String {
return read(InputStreamReader(from, encoding))
}
@JvmStatic
@Throws(IOException::class)
fun read(from: Reader): String {
val builder = StringWriter(CHAR_BUFFER_SIZE)
return try {
copy(from, builder)
builder.toString()
} finally {
close(from)
}
}
@JvmStatic
@Throws(IOException::class)
fun readBytes(from: InputStream): ByteArray {
val output = ByteArrayOutputStream(max(from.available(), BUFFER_SIZE))
try {
copy(from, output)
} finally {
close(from)
}
return output.toByteArray()
}
@Throws(IOException::class)
fun write(from: ByteArray?, to: OutputStream) {
try {
to.write(from)
to.flush()
} finally {
close(to)
}
}
@Throws(IOException::class)
fun write(from: String?, to: OutputStream?) {
write(from, OutputStreamWriter(to, Charsets.UTF_8))
}
@Throws(IOException::class)
fun write(from: CharArray?, to: Writer) {
try {
to.write(from)
to.flush()
} finally {
close(to)
}
}
@JvmStatic
@Throws(IOException::class)
fun write(from: String?, to: Writer) {
try {
to.write(from)
to.flush()
} finally {
close(to)
}
}
@Throws(IOException::class)
fun copy(from: Reader, to: Writer): Long {
val buffer = CharArray(CHAR_BUFFER_SIZE)
var read: Int
var total: Long = 0
while (from.read(buffer).also { read = it } != -1) {
to.write(buffer, 0, read)
total += read.toLong()
}
return total
}
@Throws(IOException::class)
fun copy(from: InputStream, to: OutputStream): Long {
val buffer = ByteArray(BUFFER_SIZE)
var read: Int
var total: Long = 0
while (from.read(buffer).also { read = it } != -1) {
to.write(buffer, 0, read)
total += read.toLong()
}
return total
}
fun buffer(input: InputStream?): BufferedInputStream {
return buffer(input, BUFFER_SIZE)
}
@Contract("null, _ -> new")
fun buffer(input: InputStream?, size: Int): BufferedInputStream {
return if (input is BufferedInputStream) input else BufferedInputStream(input, size)
}
fun buffer(output: OutputStream?): BufferedOutputStream {
return buffer(output, BUFFER_SIZE)
}
@Contract("null, _ -> new")
fun buffer(output: OutputStream?, size: Int): BufferedOutputStream {
return if (output is BufferedOutputStream) output else BufferedOutputStream(output, size)
}
fun buffer(input: Reader?): BufferedReader {
return buffer(input, CHAR_BUFFER_SIZE)
}
@Contract("null, _ -> new")
fun buffer(input: Reader?, size: Int): BufferedReader {
return if (input is BufferedReader) input else BufferedReader(input, size)
}
fun buffer(output: Writer?): BufferedWriter {
return buffer(output, CHAR_BUFFER_SIZE)
}
@Contract("null, _ -> new")
fun buffer(output: Writer?, size: Int): BufferedWriter {
return if (output is BufferedWriter) output else BufferedWriter(output, size)
}
@Throws(IOException::class)
fun gzip(input: InputStream?): GZIPInputStream {
return gzip(input, BUFFER_SIZE)
}
@Contract("null, _ -> new")
@Throws(IOException::class)
fun gzip(input: InputStream?, size: Int): GZIPInputStream {
return if (input is GZIPInputStream) input else GZIPInputStream(input, size)
}
@Throws(IOException::class)
fun gzip(input: OutputStream?): GZIPOutputStream {
return gzip(input, BUFFER_SIZE)
}
@Contract("null, _ -> new")
@Throws(IOException::class)
fun gzip(input: OutputStream?, size: Int): GZIPOutputStream {
return if (input is GZIPOutputStream) input else GZIPOutputStream(input, size)
}
fun close(c: Closeable?): Boolean {
if (c != null) {
try {
c.close()
return true
} catch (e: IOException) {
e.printStackTrace()
}
}
return false
}
}
@@ -0,0 +1,96 @@
package com.meloda.netservices.io
import org.jetbrains.annotations.Contract
import java.io.*
import java.math.BigInteger
object FileStreams {
val lineSeparatorChar = lineSeparator()[0]
const val ONE_KB = 1024
const val ONE_MB = ONE_KB * 1024
const val ONE_GB = ONE_MB * 1024
const val ONE_TB = ONE_GB * 1024L
const val ONE_PB = ONE_TB * 1024L
const val ONE_EB = ONE_PB * 1024L
val ONE_ZB: BigInteger = BigInteger.valueOf(ONE_EB).multiply(BigInteger.valueOf(1024L))
val ONE_YB: BigInteger = ONE_ZB.multiply(BigInteger.valueOf(1024L))
@Throws(IOException::class)
fun read(from: File?): String {
return EasyStreams.read(reader(from))
}
@Throws(IOException::class)
fun write(from: String?, to: File?) {
EasyStreams.write(from, writer(to))
}
@Throws(IOException::class)
fun write(from: ByteArray?, to: File?) {
EasyStreams.write(from, FileOutputStream(to))
}
@Throws(IOException::class)
fun append(from: ByteArray?, to: File?) {
EasyStreams.write(from, FileOutputStream(to, true))
}
@Throws(IOException::class)
fun append(from: CharArray?, to: File?) {
EasyStreams.write(from, FileWriter(to, true))
}
@Throws(IOException::class)
fun append(from: CharSequence, to: File?) {
EasyStreams.write(if (from is String) from else from.toString(), FileWriter(to, true))
}
fun delete(dir: File) {
if (dir.isDirectory) {
val files = dir.listFiles() ?: return
for (file in files) {
delete(file)
}
} else {
dir.delete()
}
}
fun lineSeparator(): String {
return System.lineSeparator()
}
fun search(dir: File, name: String?): File? {
require(dir.isDirectory) { "dir can't be file." }
val files = dir.listFiles() ?: return null
if (files.isEmpty()) {
return null
}
for (file in files) {
if (file.isDirectory) {
search(file, name)
} else if (file.name.contains(name!!)) {
return file
}
}
return null
}
@Contract("_ -> new")
@Throws(FileNotFoundException::class)
fun reader(from: File?): Reader {
return InputStreamReader(FileInputStream(from), Charsets.UTF_8)
}
@Contract("_ -> new")
@Throws(FileNotFoundException::class)
fun writer(to: File?): Writer {
return OutputStreamWriter(FileOutputStream(to), Charsets.UTF_8)
}
}