Skip to content

Commit 7d484da

Browse files
alanleedevfacebook-github-bot
authored andcommitted
Convert FileIoHandler.java to Kotlin
Summary: Java to Kotlin conversion Changelog: [Internal] Differential Revision: D72742937
1 parent f86de97 commit 7d484da

File tree

3 files changed

+164
-193
lines changed

3 files changed

+164
-193
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,9 +3224,9 @@ public abstract interface class com/facebook/react/modules/websocket/WebSocketMo
32243224
public abstract fun onMessage (Lokio/ByteString;Lcom/facebook/react/bridge/WritableMap;)V
32253225
}
32263226

3227-
public class com/facebook/react/packagerconnection/FileIoHandler : java/lang/Runnable {
3227+
public final class com/facebook/react/packagerconnection/FileIoHandler : java/lang/Runnable {
32283228
public fun <init> ()V
3229-
public fun handlers ()Ljava/util/Map;
3229+
public final fun handlers ()Ljava/util/Map;
32303230
public fun run ()V
32313231
}
32323232

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/FileIoHandler.java

Lines changed: 0 additions & 191 deletions
This file was deleted.
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.packagerconnection
9+
10+
import android.os.Handler
11+
import android.os.Looper
12+
import android.util.Base64
13+
import com.facebook.common.logging.FLog
14+
import java.io.FileInputStream
15+
import java.io.FileNotFoundException
16+
import java.io.IOException
17+
import java.util.HashMap
18+
import org.json.JSONObject
19+
20+
public class FileIoHandler : Runnable {
21+
22+
private class TtlFileInputStream(path: String?) {
23+
private val stream = FileInputStream(path)
24+
private var ttl: Long = System.currentTimeMillis() + FILE_TTL
25+
26+
private fun extendTtl() {
27+
ttl = System.currentTimeMillis() + FILE_TTL
28+
}
29+
30+
fun expiredTtl(): Boolean = System.currentTimeMillis() >= ttl
31+
32+
@Throws(IOException::class)
33+
fun read(size: Int): String {
34+
extendTtl()
35+
val buffer = ByteArray(size)
36+
val bytesRead = stream.read(buffer)
37+
return Base64.encodeToString(buffer, 0, bytesRead, Base64.DEFAULT)
38+
}
39+
40+
@Throws(IOException::class)
41+
fun close() {
42+
stream.close()
43+
}
44+
}
45+
46+
private var nextHandle = 1
47+
private val handler = Handler(Looper.getMainLooper())
48+
private val openFiles: MutableMap<Int, TtlFileInputStream> = HashMap()
49+
private val requestHandlers: MutableMap<String, RequestHandler> = HashMap()
50+
51+
init {
52+
requestHandlers["fopen"] =
53+
object : RequestOnlyHandler() {
54+
override fun onRequest(params: Any?, responder: Responder) {
55+
synchronized(openFiles) {
56+
try {
57+
val paramsObj =
58+
params as JSONObject?
59+
?: throw Exception(
60+
"params must be an object { mode: string, filename: string }")
61+
val mode = paramsObj.optString("mode") ?: throw Exception("missing params.mode")
62+
val filename =
63+
paramsObj.optString("filename") ?: throw Exception("missing params.filename")
64+
require(mode == "r") { "unsupported mode: $mode" }
65+
66+
responder.respond(addOpenFile(filename))
67+
} catch (e: Exception) {
68+
responder.error(e.toString())
69+
}
70+
}
71+
}
72+
}
73+
requestHandlers["fclose"] =
74+
object : RequestOnlyHandler() {
75+
override fun onRequest(params: Any?, responder: Responder) {
76+
synchronized(openFiles) {
77+
try {
78+
if (params !is Number) {
79+
throw Exception("params must be a file handle")
80+
}
81+
val stream =
82+
openFiles[params]
83+
?: throw Exception("invalid file handle, it might have timed out")
84+
85+
openFiles.remove(params)
86+
stream.close()
87+
responder.respond("")
88+
} catch (e: Exception) {
89+
responder.error(e.toString())
90+
}
91+
}
92+
}
93+
}
94+
requestHandlers["fread"] =
95+
object : RequestOnlyHandler() {
96+
override fun onRequest(params: Any?, responder: Responder) {
97+
synchronized(openFiles) {
98+
try {
99+
val paramsObj =
100+
params as JSONObject?
101+
?: throw Exception(
102+
"params must be an object { file: handle, size: number }")
103+
val file = paramsObj.optInt("file")
104+
if (file == 0) {
105+
throw Exception("invalid or missing file handle")
106+
}
107+
val size = paramsObj.optInt("size")
108+
if (size == 0) {
109+
throw Exception("invalid or missing read size")
110+
}
111+
val stream =
112+
openFiles[file]
113+
?: throw Exception("invalid file handle, it might have timed out")
114+
115+
responder.respond(stream.read(size))
116+
} catch (e: Exception) {
117+
responder.error(e.toString())
118+
}
119+
}
120+
}
121+
}
122+
}
123+
124+
public fun handlers(): Map<String, RequestHandler> = requestHandlers
125+
126+
@Throws(FileNotFoundException::class)
127+
private fun addOpenFile(filename: String): Int {
128+
val handle = nextHandle++
129+
openFiles[handle] = TtlFileInputStream(filename)
130+
if (openFiles.size == 1) {
131+
handler.postDelayed(this@FileIoHandler, FILE_TTL)
132+
}
133+
return handle
134+
}
135+
136+
override fun run() {
137+
// clean up files that are past their expiry date
138+
synchronized(openFiles) {
139+
openFiles.entries.removeAll { (_, stream) ->
140+
if (stream.expiredTtl()) {
141+
try {
142+
stream.close()
143+
} catch (e: IOException) {
144+
FLog.e(TAG, "Failed to close expired file", e)
145+
}
146+
true
147+
} else {
148+
false
149+
}
150+
}
151+
152+
if (openFiles.isNotEmpty()) {
153+
handler.postDelayed(this, FILE_TTL)
154+
}
155+
}
156+
}
157+
158+
private companion object {
159+
private val TAG: String = JSPackagerClient::class.java.simpleName
160+
private const val FILE_TTL = 30_000L
161+
}
162+
}

0 commit comments

Comments
 (0)