diff --git a/app/display/model/.classpath b/app/display/model/.classpath index f1cf62ee2b..17d4dbfa63 100644 --- a/app/display/model/.classpath +++ b/app/display/model/.classpath @@ -1,12 +1,61 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/display/model/.project b/app/display/model/.project index db0871a317..ddce5fcf23 100644 --- a/app/display/model/.project +++ b/app/display/model/.project @@ -10,8 +10,25 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + + + 1775148788479 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/BaseWidgetsService.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/BaseWidgetsService.java index e3d3c54f84..636411388c 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/BaseWidgetsService.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/BaseWidgetsService.java @@ -34,6 +34,7 @@ import org.csstudio.display.builder.model.widgets.PolygonWidget; import org.csstudio.display.builder.model.widgets.PolylineWidget; import org.csstudio.display.builder.model.widgets.ProgressBarWidget; +import org.csstudio.display.builder.model.widgets.PVASecurityWidget; import org.csstudio.display.builder.model.widgets.RadioWidget; import org.csstudio.display.builder.model.widgets.RectangleWidget; import org.csstudio.display.builder.model.widgets.ScaledSliderWidget; @@ -90,6 +91,7 @@ public Collection getWidgetDescriptors() PolygonWidget.WIDGET_DESCRIPTOR, PolylineWidget.WIDGET_DESCRIPTOR, ProgressBarWidget.WIDGET_DESCRIPTOR, + PVASecurityWidget.WIDGET_DESCRIPTOR, RadioWidget.WIDGET_DESCRIPTOR, RectangleWidget.WIDGET_DESCRIPTOR, ScaledSliderWidget.WIDGET_DESCRIPTOR, diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/PVASecurityWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/PVASecurityWidget.java new file mode 100644 index 0000000000..b142499ac5 --- /dev/null +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/PVASecurityWidget.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2026 Oak Ridge National Laboratory. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.csstudio.display.builder.model.widgets; + +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.newBooleanPropertyDescriptor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.newStringPropertyDescriptor; + +import java.util.List; + +import org.csstudio.display.builder.model.Widget; +import org.csstudio.display.builder.model.WidgetCategory; +import org.csstudio.display.builder.model.WidgetDescriptor; +import org.csstudio.display.builder.model.WidgetProperty; +import org.csstudio.display.builder.model.WidgetPropertyCategory; +import org.csstudio.display.builder.model.WidgetPropertyDescriptor; +import org.csstudio.display.builder.model.properties.EnumWidgetProperty; + +@SuppressWarnings("nls") +public class PVASecurityWidget extends PVWidget +{ + public enum PVASecurityMode + { + TLS_STATUS, + SERVER_IDENTITY, + CLIENT_IDENTITY, + AUTH_METHOD + } + + public static final WidgetDescriptor WIDGET_DESCRIPTOR = + new WidgetDescriptor("pva_security", WidgetCategory.MONITOR, + "PVA Security", + "/icons/led.png", + "PVAccess TLS security status and identity") + { + @Override + public Widget createWidget() + { + return new PVASecurityWidget(); + } + }; + + public static final WidgetPropertyDescriptor propDisplayMode = + new WidgetPropertyDescriptor<>(WidgetPropertyCategory.DISPLAY, "display_mode", "Display Mode") + { + @Override + public EnumWidgetProperty createProperty(final Widget widget, final PVASecurityMode default_value) + { + return new EnumWidgetProperty<>(this, widget, default_value); + } + }; + + public static final WidgetPropertyDescriptor propTLSActive = + newBooleanPropertyDescriptor(WidgetPropertyCategory.RUNTIME, "tls_active", "TLS Active"); + + public static final WidgetPropertyDescriptor propServerIdentity = + newStringPropertyDescriptor(WidgetPropertyCategory.RUNTIME, "server_identity", "Server Identity"); + + public static final WidgetPropertyDescriptor propClientIdentity = + newStringPropertyDescriptor(WidgetPropertyCategory.RUNTIME, "client_identity", "Client Identity"); + + public static final WidgetPropertyDescriptor propAuthMethod = + newStringPropertyDescriptor(WidgetPropertyCategory.RUNTIME, "auth_method", "Auth Method"); + + private volatile WidgetProperty display_mode; + private volatile WidgetProperty tls_active; + private volatile WidgetProperty server_identity; + private volatile WidgetProperty client_identity; + private volatile WidgetProperty auth_method; + + public PVASecurityWidget() + { + super(WIDGET_DESCRIPTOR.getType(), 200, 25); + } + + @Override + protected void defineProperties(final List> properties) + { + super.defineProperties(properties); + properties.add(display_mode = propDisplayMode.createProperty(this, PVASecurityMode.TLS_STATUS)); + properties.add(tls_active = propTLSActive.createProperty(this, false)); + properties.add(server_identity = propServerIdentity.createProperty(this, "")); + properties.add(client_identity = propClientIdentity.createProperty(this, "")); + properties.add(auth_method = propAuthMethod.createProperty(this, "")); + } + + public WidgetProperty propDisplayMode() + { + return display_mode; + } + + public WidgetProperty runtimePropTLSActive() + { + return tls_active; + } + + public WidgetProperty runtimePropServerIdentity() + { + return server_identity; + } + + public WidgetProperty runtimePropClientIdentity() + { + return client_identity; + } + + public WidgetProperty runtimePropAuthMethod() + { + return auth_method; + } +} diff --git a/app/display/representation-javafx/.classpath b/app/display/representation-javafx/.classpath index 3386b2efe1..c6effeb74c 100644 --- a/app/display/representation-javafx/.classpath +++ b/app/display/representation-javafx/.classpath @@ -1,11 +1,37 @@ - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18,5 +44,27 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/display/representation-javafx/.project b/app/display/representation-javafx/.project index dbe279bf03..9b8a5cfbc3 100644 --- a/app/display/representation-javafx/.project +++ b/app/display/representation-javafx/.project @@ -10,8 +10,25 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + + + 1775148840228 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/BaseWidgetRepresentations.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/BaseWidgetRepresentations.java index b6db502bd7..8576b4491f 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/BaseWidgetRepresentations.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/BaseWidgetRepresentations.java @@ -34,6 +34,7 @@ import org.csstudio.display.builder.model.widgets.PolygonWidget; import org.csstudio.display.builder.model.widgets.PolylineWidget; import org.csstudio.display.builder.model.widgets.ProgressBarWidget; +import org.csstudio.display.builder.model.widgets.PVASecurityWidget; import org.csstudio.display.builder.model.widgets.RadioWidget; import org.csstudio.display.builder.model.widgets.RectangleWidget; import org.csstudio.display.builder.model.widgets.ScaledSliderWidget; @@ -106,6 +107,7 @@ public Widget createWidget() entry(PolygonWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new PolygonRepresentation()), entry(PolylineWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new PolylineRepresentation()), entry(ProgressBarWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new ProgressBarRepresentation()), + entry(PVASecurityWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new PVASecurityRepresentation()), entry(RadioWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new RadioRepresentation()), entry(RectangleWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new RectangleRepresentation()), entry(ScaledSliderWidget.WIDGET_DESCRIPTOR, () -> (WidgetRepresentation) new ScaledSliderRepresentation()), diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/PVASecurityRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/PVASecurityRepresentation.java new file mode 100644 index 0000000000..66bd7789d0 --- /dev/null +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/PVASecurityRepresentation.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2026 Oak Ridge National Laboratory. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.csstudio.display.builder.representation.javafx.widgets; + +import org.csstudio.display.builder.model.DirtyFlag; +import org.csstudio.display.builder.model.UntypedWidgetPropertyListener; +import org.csstudio.display.builder.model.WidgetProperty; +import org.csstudio.display.builder.model.WidgetPropertyListener; +import org.csstudio.display.builder.model.widgets.PVASecurityWidget; +import org.csstudio.display.builder.model.widgets.PVASecurityWidget.PVASecurityMode; +import org.epics.vtype.VType; + +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.SVGPath; + +@SuppressWarnings("nls") +public class PVASecurityRepresentation extends JFXBaseRepresentation +{ + private static final String LOCKED_ICON = "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"; + private static final String UNLOCKED_ICON = "M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z"; + private static final String SERVER_ICON = "M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm13-6H4c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h16c.55 0 1 .45 1 1v6c0 .55-.45 1-1 1zM7 11c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"; + private static final String PERSON_ICON = "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"; + private static final String SHIELD_ICON = "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"; + + private static final Color TLS_ON = Color.web("#2e7d32"); + private static final Color TLS_OFF = Color.web("#9e9e9e"); + private static final Color SERVER = Color.web("#1565c0"); + private static final Color CLIENT = Color.web("#6a1b9a"); + private static final Color AUTH = Color.web("#e65100"); + + private final DirtyFlag dirty_size = new DirtyFlag(); + private final DirtyFlag dirty_content = new DirtyFlag(); + private final WidgetPropertyListener size_listener = this::sizeChanged; + private final UntypedWidgetPropertyListener content_listener = this::contentChanged; + + private SVGPath icon; + private Label text; + + @Override + protected HBox createJFXNode() throws Exception + { + icon = new SVGPath(); + icon.setScaleX(0.67); + icon.setScaleY(0.67); + + text = new Label(); + + final HBox box = new HBox(6, icon, text); + box.setAlignment(Pos.CENTER_LEFT); + box.setManaged(false); + return box; + } + + @Override + protected void registerListeners() + { + super.registerListeners(); + model_widget.propWidth().addPropertyListener(size_listener); + model_widget.propHeight().addPropertyListener(size_listener); + model_widget.propDisplayMode().addUntypedPropertyListener(content_listener); + model_widget.runtimePropTLSActive().addUntypedPropertyListener(content_listener); + model_widget.runtimePropServerIdentity().addUntypedPropertyListener(content_listener); + model_widget.runtimePropClientIdentity().addUntypedPropertyListener(content_listener); + model_widget.runtimePropAuthMethod().addUntypedPropertyListener(content_listener); + model_widget.runtimePropValue().addUntypedPropertyListener(content_listener); + contentChanged(null, null, null); + } + + @Override + protected void unregisterListeners() + { + model_widget.propWidth().removePropertyListener(size_listener); + model_widget.propHeight().removePropertyListener(size_listener); + model_widget.propDisplayMode().removePropertyListener(content_listener); + model_widget.runtimePropTLSActive().removePropertyListener(content_listener); + model_widget.runtimePropServerIdentity().removePropertyListener(content_listener); + model_widget.runtimePropClientIdentity().removePropertyListener(content_listener); + model_widget.runtimePropAuthMethod().removePropertyListener(content_listener); + model_widget.runtimePropValue().removePropertyListener(content_listener); + super.unregisterListeners(); + } + + private void sizeChanged(final WidgetProperty property, final Integer old_value, final Integer new_value) + { + dirty_size.mark(); + toolkit.scheduleUpdate(this); + } + + private void contentChanged(final WidgetProperty property, final Object old_value, final Object new_value) + { + dirty_content.mark(); + toolkit.scheduleUpdate(this); + } + + @Override + public void updateChanges() + { + super.updateChanges(); + if (dirty_size.checkAndClear()) + jfx_node.resize(model_widget.propWidth().getValue(), model_widget.propHeight().getValue()); + if (! dirty_content.checkAndClear()) + return; + + final PVASecurityMode mode = model_widget.propDisplayMode().getValue(); + switch (mode) + { + case SERVER_IDENTITY: + icon.setContent(SERVER_ICON); + icon.setFill(SERVER); + text.setText(orDash(model_widget.runtimePropServerIdentity().getValue())); + break; + case CLIENT_IDENTITY: + icon.setContent(PERSON_ICON); + icon.setFill(CLIENT); + text.setText(orDash(model_widget.runtimePropClientIdentity().getValue())); + break; + case AUTH_METHOD: + icon.setContent(SHIELD_ICON); + icon.setFill(AUTH); + text.setText(orDash(model_widget.runtimePropAuthMethod().getValue())); + break; + case TLS_STATUS: + default: + final VType value = model_widget.runtimePropValue().getValue(); + if (value == null) + { + icon.setContent(UNLOCKED_ICON); + icon.setFill(TLS_OFF); + text.setText("Disconnected"); + } + else if (model_widget.runtimePropTLSActive().getValue()) + { + icon.setContent(LOCKED_ICON); + icon.setFill(TLS_ON); + text.setText("TLS Secured"); + } + else + { + icon.setContent(UNLOCKED_ICON); + icon.setFill(TLS_OFF); + text.setText("Not Secured"); + } + break; + } + } + + private String orDash(final String text) + { + if (text == null || text.isBlank()) + return "—"; + return text; + } +} diff --git a/app/display/runtime/.classpath b/app/display/runtime/.classpath index 82f059f1cd..aff6ac5af5 100644 --- a/app/display/runtime/.classpath +++ b/app/display/runtime/.classpath @@ -1,19 +1,35 @@ - + - + - - - - + + + + + + + + + + + + + + + + + + + + - + @@ -24,5 +40,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/display/runtime/.project b/app/display/runtime/.project index 2f260554b9..52652a9a5d 100644 --- a/app/display/runtime/.project +++ b/app/display/runtime/.project @@ -10,8 +10,25 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + + + 1775148824115 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/app/display/runtime/pom.xml b/app/display/runtime/pom.xml index 3022ea40b7..d141b5d5f1 100644 --- a/app/display/runtime/pom.xml +++ b/app/display/runtime/pom.xml @@ -50,6 +50,11 @@ core-pv 5.0.3-SNAPSHOT + + org.phoebus + core-pv-pva + 5.0.3-SNAPSHOT + org.phoebus app-display-representation-javafx diff --git a/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/BaseWidgetRuntimes.java b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/BaseWidgetRuntimes.java index 5cd511ad70..e65b2fdbe7 100644 --- a/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/BaseWidgetRuntimes.java +++ b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/BaseWidgetRuntimes.java @@ -17,6 +17,7 @@ import org.csstudio.display.builder.model.widgets.EmbeddedDisplayWidget; import org.csstudio.display.builder.model.widgets.GroupWidget; import org.csstudio.display.builder.model.widgets.NavigationTabsWidget; +import org.csstudio.display.builder.model.widgets.PVASecurityWidget; import org.csstudio.display.builder.model.widgets.ScaledSliderWidget; import org.csstudio.display.builder.model.widgets.ScrollBarWidget; import org.csstudio.display.builder.model.widgets.TableWidget; @@ -44,6 +45,7 @@ public Map>> getWidgetRuntimeFa entry(GroupWidget.WIDGET_DESCRIPTOR.getType(), () -> new GroupWidgetRuntime()), entry(ImageWidget.WIDGET_DESCRIPTOR.getType(), () -> new ImageWidgetRuntime()), entry(NavigationTabsWidget.WIDGET_DESCRIPTOR.getType(), () -> new NavigationTabsRuntime()), + entry(PVASecurityWidget.WIDGET_DESCRIPTOR.getType(), () -> new PVASecurityRuntime()), entry(ScaledSliderWidget.WIDGET_DESCRIPTOR.getType(), () -> new SliderWidgetRuntime()), entry(ScrollBarWidget.WIDGET_DESCRIPTOR.getType(), () -> new SliderWidgetRuntime()), entry(StripchartWidget.WIDGET_DESCRIPTOR.getType(), () -> new StripchartWidgetRuntime()), diff --git a/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/PVASecurityRuntime.java b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/PVASecurityRuntime.java new file mode 100644 index 0000000000..2ab0943a63 --- /dev/null +++ b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/internal/PVASecurityRuntime.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2026 Oak Ridge National Laboratory. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.csstudio.display.builder.runtime.internal; + +import java.util.Optional; +import java.util.logging.Level; + +import org.csstudio.display.builder.model.widgets.PVASecurityWidget; +import org.csstudio.display.builder.runtime.WidgetRuntime; +import org.csstudio.display.builder.runtime.pv.PVFactory; +import org.csstudio.display.builder.runtime.pv.RuntimePV; +import org.csstudio.display.builder.runtime.pv.RuntimePVListener; +import org.epics.vtype.VType; +import org.phoebus.pv.PV; +import org.phoebus.pv.PVPool; +import org.phoebus.pv.pva.PVA_PV; + +@SuppressWarnings("nls") +public class PVASecurityRuntime extends WidgetRuntime +{ + private static final String PVA_PREFIX = "pva" + PVPool.SEPARATOR; + + private volatile RuntimePV security_pv; + private volatile boolean extra_pv_created = false; + private volatile boolean needs_refresh = true; + + private final RuntimePVListener pv_listener = new RuntimePVListener() + { + @Override + public void valueChanged(final RuntimePV pv, final VType value) + { + if (! needs_refresh) + return; + needs_refresh = false; + updateSecurityProperties(pv); + } + + @Override + public void disconnected(final RuntimePV pv) + { + needs_refresh = true; + clearSecurityProperties(); + } + }; + + @Override + public void start() + { + super.start(); + + final String pv_name = widget.propPVName().getValue(); + if (pv_name == null || pv_name.isBlank()) + return; + + if (pv_name.startsWith(PVA_PREFIX)) + { + final Optional primary = getPrimaryPV(); + if (primary.isPresent()) + { + security_pv = primary.get(); + extra_pv_created = false; + } + } + else + { + try + { + security_pv = PVFactory.getPV(PVA_PREFIX + pv_name); + extra_pv_created = true; + } + catch (Exception ex) + { + logger.log(Level.WARNING, "Cannot create PVA PV for security widget: " + pv_name, ex); + } + } + + final RuntimePV pv = security_pv; + if (pv != null) + pv.addListener(pv_listener); + } + + @Override + public void stop() + { + final RuntimePV pv = security_pv; + if (pv != null) + { + pv.removeListener(pv_listener); + if (extra_pv_created) + PVFactory.releasePV(pv); + security_pv = null; + } + extra_pv_created = false; + needs_refresh = true; + super.stop(); + } + + private void updateSecurityProperties(final RuntimePV runtime_pv) + { + final PV pv = runtime_pv.getPV(); + if (pv instanceof PVA_PV) + { + final PVA_PV pva_pv = (PVA_PV) pv; + final String server_x509 = pva_pv.getServerX509Name(); + final String client_x509 = pva_pv.getClientX509Name(); + final String auth_info = pva_pv.getAuthenticationInfo(); + final String remote_addr = pva_pv.getRemoteAddress(); + + widget.runtimePropTLSActive().setValue(pva_pv.isTLS()); + widget.runtimePropAuthMethod().setValue(safe(auth_info)); + widget.runtimePropServerIdentity().setValue( + server_x509 != null ? server_x509 : safe(remote_addr)); + widget.runtimePropClientIdentity().setValue( + client_x509 != null ? client_x509 : safe(auth_info)); + } + else + clearSecurityProperties(); + } + + private void clearSecurityProperties() + { + widget.runtimePropTLSActive().setValue(false); + widget.runtimePropServerIdentity().setValue(""); + widget.runtimePropClientIdentity().setValue(""); + widget.runtimePropAuthMethod().setValue(""); + } + + private String safe(final String value) + { + return value == null ? "" : value; + } +}