package com.battery.device.api.credentials; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.Properties; import java.util.function.Function; import com.battery.device.api.DeviceAdapterException; /** * 来源凭据的取值顺序(ADR-0065):进程工作目录下的 {@code config/vendor-credentials.properties} * → 同名环境变量 → 同名 JVM 启动参数。 * *
凭据不进数据库、不进仓库,也不打包;仓库只提交 {@code .example} 模板。 * 文件优先是为了让部署只做"复制模板填一行"这一件事;保留环境变量与启动参数两条, * 是因为交付形态可能只提供其中某一种。三者都没有时装配失败,错误信息同时点名文件路径与键名, * 使"忘了放凭据"是可见的失败而不是沉默的缺失。 * *
直连厂商库的口令({@code NEWARE_MYSQL})与推式来源的接收端点令牌({@code PUSH_INGEST})
* 都是来源凭据,因此共用同一个文件与同一套取值顺序。
*/
public final class LocalCredentials
{
/** 相对进程工作目录定位,使开发(仓库根)与交付(应用目录)用同一个位置。 */
public static final Path DEFAULT_FILE = Path.of("config", "vendor-credentials.properties");
private LocalCredentials() { }
/** 按默认位置与进程环境取值;取不到时抛出 {@link DeviceAdapterException}。 */
public static String resolve(String key)
{
return resolve(key, DEFAULT_FILE.toAbsolutePath(), System.getenv(), System::getProperty);
}
/**
* 取值顺序:文件 → 环境变量 → 启动参数。文件里的空白值不算配置过,
* 否则一个空模板会把失败推到连接阶段。
*/
public static String resolve(String key, Path credentialsFile, Map