feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包

- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等)
- java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等)
- javax/ 4个模块 (net/crypto/security/sql)
- org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http)
- dalvik/ 1个模块 (system)
- ~3053个类/接口,方法签名完全对齐Android SDK
- 桌面跨平台运行 (Windows/macOS/Linux)
- 修复所有导入错误和Python关键字冲突
This commit is contained in:
shuiyu1123 committed 2026-06-24 14:15:56 +00:00
1 parent 506f9ac725
commit a51854455b
128 files changed
+100571 -3

No files matched your search

+544
View File
@@ -0,0 +1,544 @@
"""
Java java.util.prefs standard library APIs implemented in Python.
java.util.prefs package - Preferences, PreferencesFactory, etc.
"""
from __future__ import annotations
from .._core import Stub
from ..java.lang import RuntimeException, Exception as _JavaException
import typing as _typing
import json as _json
import os as _os
import threading as _threading
__all__ = [
"Preferences", "PreferencesFactory", "AbstractPreferences",
"NodeChangeEvent", "NodeChangeListener",
"PreferenceChangeEvent", "PreferenceChangeListener",
"BackingStoreException", "InvalidPreferencesFormatException",
]
# ============================================================
# Exceptions
# ============================================================
class BackingStoreException(_JavaException):
"""java.util.prefs.BackingStoreException"""
def __init__(self, message):
super().__init__(message)
class InvalidPreferencesFormatException(_JavaException):
"""java.util.prefs.InvalidPreferencesFormatException"""
def __init__(self, message, cause=None):
super().__init__(message)
self._cause = cause
def getCause(self):
return self._cause
# ============================================================
# Event Classes
# ============================================================
class NodeChangeEvent(Stub):
"""java.util.prefs.NodeChangeEvent"""
def __init__(self, parent, child):
super().__init__()
self._parent = parent
self._child = child
def getParent(self):
return self._parent
def getChild(self):
return self._child
class PreferenceChangeEvent(Stub):
"""java.util.prefs.PreferenceChangeEvent"""
def __init__(self, node, key, new_value):
super().__init__()
self._node = node
self._key = key
self._new_value = new_value
def getNode(self):
return self._node
def getKey(self):
return self._key
def getNewValue(self):
return self._new_value
class NodeChangeListener(Stub):
"""java.util.prefs.NodeChangeListener"""
def childAdded(self, evt):
pass
def childRemoved(self, evt):
pass
class PreferenceChangeListener(Stub):
"""java.util.prefs.PreferenceChangeListener"""
def preferenceChange(self, evt):
pass
# ============================================================
# Preferences
# ============================================================
class Preferences(Stub):
"""java.util.prefs.Preferences"""
MAX_KEY_LENGTH = 80
MAX_VALUE_LENGTH = 8192
MAX_NAME_LENGTH = 80
def __init__(self, name="", parent=None):
super().__init__()
self._name = name
self._parent = parent
self._children = {}
self._prefs = {}
self._node_listeners = []
self._pref_listeners = []
self._absolute_path = self._build_path()
def _build_path(self):
if self._parent is None:
return "/" + self._name if self._name else "/"
parent_path = self._parent._absolute_path
if parent_path == "/":
return "/" + self._name
return parent_path + "/" + self._name
def put(self, key, value):
if len(key) > Preferences.MAX_KEY_LENGTH:
raise IllegalArgumentException(f"Key too long: {len(key)}")
if len(value) > Preferences.MAX_VALUE_LENGTH:
raise IllegalArgumentException(f"Value too long: {len(value)}")
self._prefs[key] = value
self._fire_preference_change(key, value)
def get(self, key, default_value):
return self._prefs.get(key, default_value)
def remove(self, key):
if key in self._prefs:
old = self._prefs.pop(key)
self._fire_preference_change(key, None)
def clear(self):
self._prefs.clear()
def putInt(self, key, value):
self.put(key, str(value))
def getInt(self, key, default_value):
val = self.get(key, None)
if val is None:
return default_value
try:
return int(val)
except ValueError:
return default_value
def putLong(self, key, value):
self.put(key, str(value))
def getLong(self, key, default_value):
val = self.get(key, None)
if val is None:
return default_value
try:
return int(val)
except ValueError:
return default_value
def putFloat(self, key, value):
self.put(key, str(value))
def getFloat(self, key, default_value):
val = self.get(key, None)
if val is None:
return default_value
try:
return float(val)
except ValueError:
return default_value
def putDouble(self, key, value):
self.put(key, str(value))
def getDouble(self, key, default_value):
val = self.get(key, None)
if val is None:
return default_value
try:
return float(val)
except ValueError:
return default_value
def putBoolean(self, key, value):
self.put(key, "true" if value else "false")
def getBoolean(self, key, default_value):
val = self.get(key, None)
if val is None:
return default_value
return val.lower() == "true"
def putByteArray(self, key, value):
import base64
self.put(key, base64.b64encode(value).decode())
def getByteArray(self, key, default_value):
import base64
val = self.get(key, None)
if val is None:
return default_value
try:
return base64.b64decode(val)
except Exception:
return default_value
def keys(self):
return list(self._prefs.keys())
def childrenNames(self):
return list(self._children.keys())
def parent(self):
return self._parent
def node(self, path_name):
if path_name.startswith("/"):
return self._root()._node_path(path_name[1:])
return self._node_path(path_name)
def nodeExists(self, path_name):
try:
self.node(path_name)
return True
except BackingStoreException:
return False
def removeNode(self):
if self._parent is not None:
self._parent._remove_child(self._name)
def name(self):
return self._name
def absolutePath(self):
return self._absolute_path
def isUserNode(self):
return False
def toString(self):
return self._absolute_path
def flush(self):
pass
def sync(self):
pass
def addNodeChangeListener(self, listener):
self._node_listeners.append(listener)
def removeNodeChangeListener(self, listener):
if listener in self._node_listeners:
self._node_listeners.remove(listener)
def addPreferenceChangeListener(self, listener):
self._pref_listeners.append(listener)
def removePreferenceChangeListener(self, listener):
if listener in self._pref_listeners:
self._pref_listeners.remove(listener)
def exportNode(self, output_stream):
data = self._to_dict()
output_stream.write(_json.dumps(data, indent=2).encode())
def exportSubtree(self, output_stream):
data = self._to_dict(recursive=True)
output_stream.write(_json.dumps(data, indent=2).encode())
def _to_dict(self, recursive=False):
result = {"prefs": dict(self._prefs)}
if recursive:
result["children"] = {
name: child._to_dict(recursive=True)
for name, child in self._children.items()
}
return result
def _root(self):
if self._parent is None:
return self
return self._parent._root()
def _node_path(self, path):
if not path:
return self
parts = path.split("/")
current = self
for part in parts:
if not part:
continue
if part == "..":
if current._parent is not None:
current = current._parent
continue
if part not in current._children:
current._children[part] = Preferences(part, current)
current = current._children[part]
return current
def _remove_child(self, name):
if name in self._children:
child = self._children.pop(name)
evt = NodeChangeEvent(self, child)
for listener in self._node_listeners:
listener.childRemoved(evt)
def _fire_preference_change(self, key, value):
evt = PreferenceChangeEvent(self, key, value)
for listener in self._pref_listeners:
listener.preferenceChange(evt)
@staticmethod
def userRoot():
if Preferences._user_root is None:
Preferences._user_root = Preferences("")
return Preferences._user_root
@staticmethod
def systemRoot():
if Preferences._system_root is None:
Preferences._system_root = Preferences("")
return Preferences._system_root
@staticmethod
def importPreferences(input_stream):
data = _json.loads(input_stream.read())
root = Preferences("")
root._prefs = data.get("prefs", {})
return root
_user_root = None
_system_root = None
# ============================================================
# AbstractPreferences
# ============================================================
class AbstractPreferences(Preferences):
"""java.util.prefs.AbstractPreferences"""
def __init__(self, parent, name):
super().__init__(name, parent)
self._is_removed = False
self._lock = _threading.RLock()
def put(self, key, value):
with self._lock:
if self._is_removed:
raise BackingStoreException("Node has been removed")
super().put(key, value)
def get(self, key, default_value):
with self._lock:
if self._is_removed:
raise BackingStoreException("Node has been removed")
return super().get(key, default_value)
def remove(self, key):
with self._lock:
super().remove(key)
def keys(self):
with self._lock:
return super().keys()
def childrenNames(self):
with self._lock:
return super().childrenNames()
def node(self, path_name):
with self._lock:
return super().node(path_name)
def removeNode(self):
with self._lock:
super().removeNode()
self._is_removed = True
def flush(self):
pass
def sync(self):
pass
def isUserNode(self):
return False
# ============================================================
# PreferencesFactory
# ============================================================
class PreferencesFactory(Stub):
"""java.util.prefs.PreferencesFactory"""
def systemRoot(self):
return Preferences.systemRoot()
def userRoot(self):
return Preferences.userRoot()
# ============================================================
# IllegalArgumentException
# ============================================================
class IllegalArgumentException(RuntimeException):
"""java.lang.IllegalArgumentException"""
pass
# ============================================================
# Preferences utility helpers
# ============================================================
class _PreferencesService(Stub):
"""Helper to manage Preferences with file-backed storage"""
def __init__(self, root_path=None):
super().__init__()
if root_path is None:
import os
root_path = os.path.join(os.path.expanduser("~"), ".java", "prefs")
self._root_path = root_path
self._cache = {}
def loadPreferences(self, node_path):
import os
import json
file_path = os.path.join(self._root_path, node_path.replace("/", "_") + ".json")
prefs = Preferences(node_path)
if os.path.exists(file_path):
try:
with open(file_path, "r") as f:
data = json.load(f)
for key, val in data.items():
prefs.put(key, val)
except Exception:
pass
self._cache[node_path] = prefs
return prefs
def savePreferences(self, prefs):
import os
import json
file_path = os.path.join(self._root_path,
prefs.absolutePath().replace("/", "_") + ".json")
os.makedirs(os.path.dirname(file_path), exist_ok=True)
data = {}
for key in prefs.keys():
data[key] = prefs.get(key, None)
with open(file_path, "w") as f:
json.dump(data, f, indent=2)
def clearCache(self):
self._cache.clear()
class _EventDispatchThread(Stub):
"""Helper for dispatching preference change events"""
def __init__(self):
super().__init__()
self._listeners = []
import threading
self._lock = threading.Lock()
def addListener(self, listener):
with self._lock:
self._listeners.append(listener)
def removeListener(self, listener):
with self._lock:
if listener in self._listeners:
self._listeners.remove(listener)
def dispatchEvent(self, event):
with self._lock:
for listener in self._listeners:
try:
if hasattr(listener, 'preferenceChange'):
listener.preferenceChange(event)
elif callable(listener):
listener(event)
except Exception:
pass
def getListeners(self):
with self._lock:
return list(self._listeners)
# ============================================================
# FileSystemPreferences - persistent Preferences backed by file
# ============================================================
class FileSystemPreferences(AbstractPreferences):
"""java.util.prefs.FileSystemPreferences - persistent file-backed preferences"""
def __init__(self, parent, name, storage_path=None):
super().__init__(parent, name)
import os
if storage_path is None:
storage_path = os.path.join(os.path.expanduser("~"), ".java", "user_prefs")
self._storage_path = os.path.join(
storage_path, self.absolutePath().replace("/", "_") + ".xml"
)
self._loaded = False
self._service = _PreferencesService(storage_path)
def _ensureLoaded(self):
if not self._loaded:
try:
import os
if os.path.exists(self._storage_path):
node = self._service.loadPreferences(self.absolutePath())
for key in node.keys():
self._prefs[key] = node.get(key, "")
self._loaded = True
except Exception:
self._loaded = True
def put(self, key, value):
self._ensureLoaded()
super().put(key, value)
def get(self, key, default_value):
self._ensureLoaded()
return super().get(key, default_value)
def keys(self):
self._ensureLoaded()
return super().keys()
def flush(self):
self._service.savePreferences(self)
super().flush()
def sync(self):
self._ensureLoaded()
self._service.savePreferences(self)