mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Convert FileIoHandler.java to Kotlin (#50612)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50612 Java to Kotlin conversion Changelog: [Internal] Reviewed By: cortinico Differential Revision: D72742937 fbshipit-source-id: b72b51460555226fa7fe99f4ca5290f46c478291
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c51c4b1922
commit
61c539fa6a
@@ -3238,9 +3238,9 @@ public abstract interface class com/facebook/react/modules/websocket/WebSocketMo
|
||||
public abstract fun onMessage (Lokio/ByteString;Lcom/facebook/react/bridge/WritableMap;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/packagerconnection/FileIoHandler : java/lang/Runnable {
|
||||
public final class com/facebook/react/packagerconnection/FileIoHandler : java/lang/Runnable {
|
||||
public fun <init> ()V
|
||||
public fun handlers ()Ljava/util/Map;
|
||||
public final fun handlers ()Ljava/util/Map;
|
||||
public fun run ()V
|
||||
}
|
||||
|
||||
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.packagerconnection;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Base64;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
public class FileIoHandler implements Runnable {
|
||||
private static final String TAG = JSPackagerClient.class.getSimpleName();
|
||||
private static final long FILE_TTL = 30 * 1000;
|
||||
|
||||
private static class TtlFileInputStream {
|
||||
private final FileInputStream mStream;
|
||||
private long mTtl;
|
||||
|
||||
public TtlFileInputStream(String path) throws FileNotFoundException {
|
||||
mStream = new FileInputStream(path);
|
||||
mTtl = System.currentTimeMillis() + FILE_TTL;
|
||||
}
|
||||
|
||||
private void extendTtl() {
|
||||
mTtl = System.currentTimeMillis() + FILE_TTL;
|
||||
}
|
||||
|
||||
public boolean expiredTtl() {
|
||||
return System.currentTimeMillis() >= mTtl;
|
||||
}
|
||||
|
||||
public String read(int size) throws IOException {
|
||||
extendTtl();
|
||||
byte[] buffer = new byte[size];
|
||||
int bytesRead = mStream.read(buffer);
|
||||
return Base64.encodeToString(buffer, 0, bytesRead, Base64.DEFAULT);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
mStream.close();
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
private int mNextHandle;
|
||||
private final Handler mHandler;
|
||||
private final Map<Integer, TtlFileInputStream> mOpenFiles;
|
||||
private final Map<String, RequestHandler> mRequestHandlers;
|
||||
|
||||
public FileIoHandler() {
|
||||
mNextHandle = 1;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mOpenFiles = new HashMap<>();
|
||||
mRequestHandlers = new HashMap<>();
|
||||
mRequestHandlers.put(
|
||||
"fopen",
|
||||
new RequestOnlyHandler() {
|
||||
@Override
|
||||
public void onRequest(@Nullable Object params, Responder responder) {
|
||||
synchronized (mOpenFiles) {
|
||||
try {
|
||||
JSONObject paramsObj = (JSONObject) params;
|
||||
if (paramsObj == null) {
|
||||
throw new Exception(
|
||||
"params must be an object { mode: string, filename: string }");
|
||||
}
|
||||
String mode = paramsObj.optString("mode");
|
||||
if (mode == null) {
|
||||
throw new Exception("missing params.mode");
|
||||
}
|
||||
String filename = paramsObj.optString("filename");
|
||||
if (filename == null) {
|
||||
throw new Exception("missing params.filename");
|
||||
}
|
||||
if (!mode.equals("r")) {
|
||||
throw new IllegalArgumentException("unsupported mode: " + mode);
|
||||
}
|
||||
|
||||
responder.respond(addOpenFile(filename));
|
||||
} catch (Exception e) {
|
||||
responder.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mRequestHandlers.put(
|
||||
"fclose",
|
||||
new RequestOnlyHandler() {
|
||||
@Override
|
||||
public void onRequest(@Nullable Object params, Responder responder) {
|
||||
synchronized (mOpenFiles) {
|
||||
try {
|
||||
if (!(params instanceof Number)) {
|
||||
throw new Exception("params must be a file handle");
|
||||
}
|
||||
TtlFileInputStream stream = mOpenFiles.get(params);
|
||||
if (stream == null) {
|
||||
throw new Exception("invalid file handle, it might have timed out");
|
||||
}
|
||||
|
||||
mOpenFiles.remove(params);
|
||||
stream.close();
|
||||
responder.respond("");
|
||||
} catch (Exception e) {
|
||||
responder.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mRequestHandlers.put(
|
||||
"fread",
|
||||
new RequestOnlyHandler() {
|
||||
@Override
|
||||
public void onRequest(@Nullable Object params, Responder responder) {
|
||||
synchronized (mOpenFiles) {
|
||||
try {
|
||||
JSONObject paramsObj = (JSONObject) params;
|
||||
if (paramsObj == null) {
|
||||
throw new Exception("params must be an object { file: handle, size: number }");
|
||||
}
|
||||
int file = paramsObj.optInt("file");
|
||||
if (file == 0) {
|
||||
throw new Exception("invalid or missing file handle");
|
||||
}
|
||||
int size = paramsObj.optInt("size");
|
||||
if (size == 0) {
|
||||
throw new Exception("invalid or missing read size");
|
||||
}
|
||||
TtlFileInputStream stream = mOpenFiles.get(file);
|
||||
if (stream == null) {
|
||||
throw new Exception("invalid file handle, it might have timed out");
|
||||
}
|
||||
|
||||
responder.respond(stream.read(size));
|
||||
} catch (Exception e) {
|
||||
responder.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, RequestHandler> handlers() {
|
||||
return mRequestHandlers;
|
||||
}
|
||||
|
||||
private int addOpenFile(String filename) throws FileNotFoundException {
|
||||
int handle = mNextHandle++;
|
||||
mOpenFiles.put(handle, new TtlFileInputStream(filename));
|
||||
if (mOpenFiles.size() == 1) {
|
||||
mHandler.postDelayed(FileIoHandler.this, FILE_TTL);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// clean up files that are past their expiry date
|
||||
synchronized (mOpenFiles) {
|
||||
Iterator<TtlFileInputStream> i = mOpenFiles.values().iterator();
|
||||
while (i.hasNext()) {
|
||||
TtlFileInputStream stream = i.next();
|
||||
if (stream.expiredTtl()) {
|
||||
i.remove();
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
FLog.e(TAG, "closing expired file failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mOpenFiles.isEmpty()) {
|
||||
mHandler.postDelayed(this, FILE_TTL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.packagerconnection
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Base64
|
||||
import com.facebook.common.logging.FLog
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import org.json.JSONObject
|
||||
|
||||
public class FileIoHandler : Runnable {
|
||||
|
||||
private class TtlFileInputStream(path: String?) {
|
||||
private val stream = FileInputStream(path)
|
||||
private var ttl: Long = System.currentTimeMillis() + FILE_TTL
|
||||
|
||||
private fun extendTtl() {
|
||||
ttl = System.currentTimeMillis() + FILE_TTL
|
||||
}
|
||||
|
||||
fun expiredTtl(): Boolean = System.currentTimeMillis() >= ttl
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun read(size: Int): String {
|
||||
extendTtl()
|
||||
val buffer = ByteArray(size)
|
||||
val bytesRead = stream.read(buffer)
|
||||
return Base64.encodeToString(buffer, 0, bytesRead, Base64.DEFAULT)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun close() {
|
||||
stream.close()
|
||||
}
|
||||
}
|
||||
|
||||
private var nextHandle = 1
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private val openFiles: MutableMap<Int, TtlFileInputStream> = mutableMapOf()
|
||||
private val requestHandlers: MutableMap<String, RequestHandler> = mutableMapOf()
|
||||
|
||||
init {
|
||||
requestHandlers["fopen"] =
|
||||
object : RequestOnlyHandler() {
|
||||
override fun onRequest(params: Any?, responder: Responder) {
|
||||
synchronized(openFiles) {
|
||||
try {
|
||||
val paramsObj =
|
||||
params as JSONObject?
|
||||
?: throw Exception(
|
||||
"params must be an object { mode: string, filename: string }")
|
||||
val mode = paramsObj.optString("mode") ?: throw Exception("missing params.mode")
|
||||
val filename =
|
||||
paramsObj.optString("filename") ?: throw Exception("missing params.filename")
|
||||
require(mode == "r") { "unsupported mode: $mode" }
|
||||
|
||||
responder.respond(addOpenFile(filename))
|
||||
} catch (e: Exception) {
|
||||
responder.error(e.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
requestHandlers["fclose"] =
|
||||
object : RequestOnlyHandler() {
|
||||
override fun onRequest(params: Any?, responder: Responder) {
|
||||
synchronized(openFiles) {
|
||||
try {
|
||||
if (params !is Number) {
|
||||
throw Exception("params must be a file handle")
|
||||
}
|
||||
val stream =
|
||||
openFiles[params]
|
||||
?: throw Exception("invalid file handle, it might have timed out")
|
||||
|
||||
openFiles.remove(params)
|
||||
stream.close()
|
||||
responder.respond("")
|
||||
} catch (e: Exception) {
|
||||
responder.error(e.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
requestHandlers["fread"] =
|
||||
object : RequestOnlyHandler() {
|
||||
override fun onRequest(params: Any?, responder: Responder) {
|
||||
synchronized(openFiles) {
|
||||
try {
|
||||
val paramsObj =
|
||||
params as JSONObject?
|
||||
?: throw Exception(
|
||||
"params must be an object { file: handle, size: number }")
|
||||
val file = paramsObj.optInt("file")
|
||||
if (file == 0) {
|
||||
throw Exception("invalid or missing file handle")
|
||||
}
|
||||
val size = paramsObj.optInt("size")
|
||||
if (size == 0) {
|
||||
throw Exception("invalid or missing read size")
|
||||
}
|
||||
val stream =
|
||||
openFiles[file]
|
||||
?: throw Exception("invalid file handle, it might have timed out")
|
||||
|
||||
responder.respond(stream.read(size))
|
||||
} catch (e: Exception) {
|
||||
responder.error(e.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun handlers(): Map<String, RequestHandler> = requestHandlers
|
||||
|
||||
@Throws(FileNotFoundException::class)
|
||||
private fun addOpenFile(filename: String): Int {
|
||||
val handle = nextHandle++
|
||||
openFiles[handle] = TtlFileInputStream(filename)
|
||||
if (openFiles.size == 1) {
|
||||
handler.postDelayed(this@FileIoHandler, FILE_TTL)
|
||||
}
|
||||
return handle
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
// clean up files that are past their expiry date
|
||||
synchronized(openFiles) {
|
||||
openFiles.entries.removeAll { (_, stream) ->
|
||||
if (stream.expiredTtl()) {
|
||||
try {
|
||||
stream.close()
|
||||
} catch (e: IOException) {
|
||||
FLog.e(TAG, "Failed to close expired file", e)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
if (openFiles.isNotEmpty()) {
|
||||
handler.postDelayed(this, FILE_TTL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val TAG: String = JSPackagerClient::class.java.simpleName
|
||||
private const val FILE_TTL = 30_000L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user