| | |
| | | import java.util.Locale; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | import java.util.function.Function; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | |
| | | /** 管理启用设备适配器的运行时实例及其会话生命周期。 */ |
| | |
| | | } |
| | | |
| | | /** 按持久化配置注册、替换或移除运行时实例。 */ |
| | | public synchronized void synchronize(AdapterInstanceConfig config) |
| | | public void synchronize(AdapterInstanceConfig config) |
| | | { |
| | | Objects.requireNonNull(config, "config"); |
| | | if (!config.enabled()) |
| | |
| | | return; |
| | | } |
| | | |
| | | RegisteredAdapter previous; |
| | | synchronized (this) |
| | | { |
| | | RegisteredAdapter current = adapters.get(config.adapterCode()); |
| | | if (current != null && current.config().equals(config)) return; |
| | | if (current != null && current.config.equals(config)) return; |
| | | |
| | | DeviceAdapterFactory factory = factories.get(normalizeType(config.adapterType())); |
| | | if (factory == null) throw new AdapterRegistryException("Unsupported device adapter type: " + config.adapterType()); |
| | | if (factory == null) |
| | | throw new AdapterRegistryException("Unsupported device adapter type: " + config.adapterType()); |
| | | |
| | | DeviceAdapter replacement = factory.create(config); |
| | | RegisteredAdapter previous = adapters.put(config.adapterCode(), new RegisteredAdapter(config, replacement)); |
| | | if (previous != null) previous.adapter().close(); |
| | | previous = adapters.put(config.adapterCode(), new RegisteredAdapter(config, replacement)); |
| | | } |
| | | closeWhenIdle(previous); |
| | | } |
| | | |
| | | /** 返回已启用适配器;未注册时给出可识别失败。 */ |
| | | public synchronized DeviceAdapter require(String adapterCode) |
| | | /** 在实例级串行边界内执行一次适配器操作;未注册时给出可识别失败。 */ |
| | | public <T> T execute(String adapterCode, Function<DeviceAdapter, T> operation) |
| | | { |
| | | RegisteredAdapter registered = adapters.get(adapterCode); |
| | | if (registered == null) throw new AdapterRegistryException("Device adapter is not enabled: " + adapterCode); |
| | | return registered.adapter(); |
| | | Objects.requireNonNull(operation, "operation"); |
| | | RegisteredAdapter registered; |
| | | synchronized (this) |
| | | { |
| | | registered = adapters.get(adapterCode); |
| | | if (registered == null) |
| | | throw new AdapterRegistryException("Device adapter is not enabled: " + adapterCode); |
| | | registered.operationLock.lock(); |
| | | } |
| | | try |
| | | { |
| | | return operation.apply(registered.adapter); |
| | | } |
| | | finally |
| | | { |
| | | registered.operationLock.unlock(); |
| | | } |
| | | } |
| | | |
| | | public synchronized boolean contains(String adapterCode) |
| | |
| | | } |
| | | |
| | | @Override |
| | | public synchronized void close() |
| | | public void close() |
| | | { |
| | | adapters.values().forEach(registered -> registered.adapter().close()); |
| | | List<RegisteredAdapter> registered; |
| | | synchronized (this) |
| | | { |
| | | registered = List.copyOf(adapters.values()); |
| | | adapters.clear(); |
| | | } |
| | | registered.forEach(this::closeWhenIdle); |
| | | } |
| | | |
| | | private void remove(String adapterCode) |
| | | { |
| | | RegisteredAdapter previous = adapters.remove(adapterCode); |
| | | if (previous != null) previous.adapter().close(); |
| | | RegisteredAdapter previous; |
| | | synchronized (this) |
| | | { |
| | | previous = adapters.remove(adapterCode); |
| | | } |
| | | closeWhenIdle(previous); |
| | | } |
| | | |
| | | private void closeWhenIdle(RegisteredAdapter registered) |
| | | { |
| | | if (registered == null) return; |
| | | registered.operationLock.lock(); |
| | | try |
| | | { |
| | | registered.adapter.close(); |
| | | } |
| | | finally |
| | | { |
| | | registered.operationLock.unlock(); |
| | | } |
| | | } |
| | | |
| | | private static String normalizeType(String value) |
| | |
| | | return Objects.requireNonNull(value, "adapterType").trim().toUpperCase(Locale.ROOT); |
| | | } |
| | | |
| | | private record RegisteredAdapter(AdapterInstanceConfig config, DeviceAdapter adapter) |
| | | private static final class RegisteredAdapter |
| | | { |
| | | private final AdapterInstanceConfig config; |
| | | private final DeviceAdapter adapter; |
| | | private final ReentrantLock operationLock = new ReentrantLock(true); |
| | | |
| | | private RegisteredAdapter(AdapterInstanceConfig config, DeviceAdapter adapter) |
| | | { |
| | | this.config = config; |
| | | this.adapter = adapter; |
| | | } |
| | | } |
| | | } |