+ * This method performs the following steps: + *
+ * Responsibilities: + *
+ * Behavior differs based on the running side: + *
+ * Behavior: + *
+ * Contains all information required for resolving an InfoName: + *
+ * Contains: + *
+ * If running on a client, forwards the result to the client-side API. + */ + @Override + protected void onResponseCodeRead(PacketHandler handler, ObjectInputStream in) { + if (bridge.isRunningAsClient()) { + bridge.getProtocolClient().onResponse(status, records); + } + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java index ca4a928..3ce71da 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java @@ -4,18 +4,36 @@ import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseCode; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +/** + * Internal compatibility packet used when a classic-protocol packet is received + * but not supported by the current protocol version. + *
+ * Instead of rejecting the packet entirely, the content and class name are forwarded + * to the appropriate compatibility handler: + *
+ * The client requests a specific record type for a given TLN, name and optional subname. + * After sending the packet, {@link #onQuerySent(String, String, String, INSRecordType)} is invoked. * - * @param infoName the InfoName to validate. - * @throws IOException if there are I/O issues during the validation process. - * @throws ClassNotFoundException if there are issues with class loading during packet handling. + * @param tln The TLN. + * @param name The InfoName. + * @param sub Optional subname or {@code null}. + * @param type The requested record type. + * @throws IOException If sending the packet fails. + * @throws ClassNotFoundException If packet serialization fails. */ - public final void validateInfoName(InfoName infoName) throws IOException, ClassNotFoundException { - // Send Classic_PingPacket if classic protocol is supported - Classic_PingPacket cPingPacket = new Classic_PingPacket(new Classic_RequestDomain(infoName.getName(), infoName.getTopLevelName(), infoName.getPath(), protocolBridge), null, false, protocolBridge); - if (protocolBridge.isClassicSupported()) clientToINS.sendPacket(cPingPacket); + public final void sendINSQuery(String tln, String name, String sub, INSRecordType type) throws IOException, ClassNotFoundException { + if (!protocolBridge.isRunningAsClient()) return; - // Send ValidateInfoNamePacket - clientToINS.sendPacket(new ValidateInfoNamePacket(infoName, protocolBridge)); + getClientINSConnection().sendPacket(new INSQueryPacket(tln, name, sub, type, getClientINSConnection().getClientID())); + onQuerySent(tln, name, sub, type); } /** - * Requests the destination for the specified InfoName from the INS server. + * Called when the client receives an INS response from the server. + *
*
- * @param infoName the InfoName for which to request the destination.
- * @param responseCode the expected INSResponseCode for the request.
- * @throws IOException if there are I/O issues during the request process.
- * @throws ClassNotFoundException if there are issues with class loading during packet handling.
+ * @param status The response status from the server.
+ * @param records The list of records returned by the server.
*/
- public final void requestInfoName(InfoName infoName, INSResponseCode responseCode) throws IOException, ClassNotFoundException {
- // Send Classic_DomainPacket if classic protocol is supported
- Classic_DomainPacket cDomainPacket = new Classic_DomainPacket(0, new Classic_RequestDomain(infoName.getName(), infoName.getTopLevelName(), infoName.getPath(), protocolBridge), null, protocolBridge);
- if (protocolBridge.isClassicSupported()) clientToINS.sendPacket(cDomainPacket);
+ public abstract void onResponse(INSResponseStatus status, List
+ *
+ * @param tln The TLN requested.
+ * @param name The InfoName.
+ * @param sub Optional subname.
+ * @param type The requested record type.
+ */
+ public void onQuerySent(String tln, String name, String sub, INSRecordType type) {
}
- /**
- * Callback method invoked when InfoName validation is completed.
- *
- * @param infoName the InfoName that was validated.
- * @param responseCode the INSResponseCode resulting from the validation.
- */
- public abstract void validationCompleted(InfoName infoName, INSResponseCode responseCode);
-
- /**
- * Callback method invoked when the destination retrieval is completed.
- *
- * @param infoName the InfoName for which the destination was requested.
- * @param destination the retrieved destination as a string.
- * @param validationResponse the INSResponseCode resulting from the destination retrieval.
- */
- public abstract void getDestinationCompleted(InfoName infoName, String destination, INSResponseCode validationResponse);
-
/**
* Manages the folder structure for client certificates.
*/
diff --git a/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java b/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java
deleted file mode 100644
index d9dd94c..0000000
--- a/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package org.openautonomousconnection.protocol.side.client;
-
-import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient;
-import lombok.Getter;
-import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
-import org.openautonomousconnection.protocol.versions.ProtocolVersion;
-import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
-
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.net.ConnectException;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.Socket;
-
-/**
- * WebClient handles secure connections to web servers through a pipeline connection.
- * It manages SSL/TLS handshakes and data transmission over the established connection.
- */
-@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.INS)
-public final class WebClient {
- /**
- * NetworkClient instance for managing the pipeline connection to the web server.
- */
- private final NetworkClient clientToWebPipeline;
- /**
- * The Protocol Client associated with this protocol client.
- */
- @Getter
- private final ProtocolClient protocolClient;
- /**
- * SSLSocket for secure communication with the web server.
- */
- private SSLSocket clientToWebServer;
- /**
- * Streams for object serialization over the SSL connection.
- */
- private ObjectOutputStream outputStream;
- /**
- * Streams for object serialization over the SSL connection.
- */
- private ObjectInputStream inputStream;
-
- /**
- * Constructs a WebClient instance and establishes a secure connection to the web server.
- *
- * @param infoName The InfoName information for the web server.
- * @param pipelinePort The port for the pipeline connection.
- * @param webPort The port for the web server connection.
- * @param protocolClient The Protocol Client associated with this protocol client.
- * @throws Exception If an error occurs during connection setup.
- */
- public WebClient(InfoName infoName, int pipelinePort, int webPort, ProtocolClient protocolClient) throws Exception {
- this.protocolClient = protocolClient;
-
- // Initialize and connect the pipeline client
- clientToWebPipeline = new NetworkClient.ClientBuilder().
- // Set logger from ProtocolBridge
- setLogger(protocolClient.getProtocolBridge().getLogger()).
- // Set the destination and port for the pipeline connection
- setHost(infoName.getDestination(protocolClient.getProtocolBridge())).setPort(pipelinePort).
-
- // Configure packet handler and event manager
- setPacketHandler(protocolClient.getProtocolBridge().getProtocolSettings().packetHandler).
- setEventManager(protocolClient.getProtocolBridge().getProtocolSettings().eventManager).
-
- // Set proxy and ssl parameters from INS connection settings
- setProxy(protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().getProxy()).
- setSSLParameters(protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().getSocket().getSSLParameters()).
-
- // Set certificates and folders for SSL
- setRootCAFolder(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicCAFolder).
- setClientCertificatesFolder(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicClientFolder,
- protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().privateClientFolder).
-
-
- // Finalize the client setup
- build();
-
- // Connect to the pipeline
- clientToWebPipeline.connect();
-
- // Wait until the pipeline connection is established
- while (!clientToWebPipeline.isConnected()) if (clientToWebPipeline.isConnected()) break;
-
- // Create SSL socket factory using client certificates
- SSLSocketFactory sslSocketFactory = NetworkClient.ClientBuilder.
- createSSLSocketFactory(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicCAFolder,
- protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicClientFolder,
- protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().privateClientFolder);
-
- // Get proxy settings from the pipeline client
- Proxy proxy = clientToWebPipeline.getProxy();
-
- // Establish SSL connection to the web server
- SSLSocket tempSocket;
- if (sslSocketFactory == null) {
- throw new ConnectException("SSL socket factory not set. Client certificate required!");
- } else {
- // Create raw socket and wrap it in SSL socket
- if (proxy != null) {
- Socket rawSocket = new Socket(proxy);
- rawSocket.connect(new InetSocketAddress(infoName.getDestination(protocolClient.getProtocolBridge()), webPort), 0);
- tempSocket = (SSLSocket) sslSocketFactory.createSocket(rawSocket, infoName.getDestination(protocolClient.getProtocolBridge()), webPort, true);
- } else {
- tempSocket = (SSLSocket) sslSocketFactory.createSocket(infoName.getDestination(protocolClient.getProtocolBridge()), webPort);
- }
-
- clientToWebServer = tempSocket;
-
- // Configure SSL parameters
- SSLParameters sslParameters = clientToWebPipeline.getSocket().getSSLParameters();
-
- if (sslParameters != null) {
- clientToWebServer.setSSLParameters(sslParameters);
- } else {
- // Set default to TLSv1.3 if no parameters are provided
- SSLParameters defaultParams = clientToWebServer.getSSLParameters();
- defaultParams.setProtocols(new String[]{"TLSv1.3"});
- clientToWebServer.setSSLParameters(defaultParams);
- }
-
- // Configure socket options
- clientToWebServer.setTcpNoDelay(true);
- clientToWebServer.setSoTimeout(0);
-
- try {
- this.clientToWebServer.startHandshake();
- } catch (Exception handshakeEx) {
- throw new ConnectException("Handshake failed: " + handshakeEx.getMessage());
- }
-
- // Initialize object streams for communication
- this.outputStream = new ObjectOutputStream(clientToWebServer.getOutputStream());
- this.inputStream = new ObjectInputStream(clientToWebServer.getInputStream());
-
- // Start the receive thread
- this.receiveThread.start();
- }
- }
-
- /**
- * Gets the NetworkClient used for the pipeline connection to the web server.
- *
- * @return The NetworkClient connected to the web server pipeline.
- */
- public NetworkClient getClientPipelineConnection() {
- return clientToWebPipeline;
- }
-
- /**
- * Gets the SSLSocket used for communication with the web server.
- *
- * @return The SSLSocket connected to the web server.
- */
- public SSLSocket getClientWebConnection() {
- return clientToWebServer;
- } /**
- * Thread for receiving data from the web server.
- */
- private final Thread receiveThread = new Thread(this::receive);
-
- /**
- * Checks if the WebClient is currently connected to the web server.
- *
- * @return true if connected, false otherwise.
- */
- public boolean isConnected() {
- return this.clientToWebServer != null && this.clientToWebServer.isConnected() && !this.clientToWebServer.isClosed()
- && this.receiveThread.isAlive() && !this.receiveThread.isInterrupted() &&
- protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().isConnected() && clientToWebPipeline.isConnected();
- }
-
- /**
- * Continuously receives data from the web server.
- * This method runs in a separate thread and handles incoming objects.
- * If an error occurs, it attempts to close the connection.
- */
- private void receive() {
- try {
- while (this.isConnected()) {
- Object received = this.inputStream.readObject();
- }
- } catch (Exception var2) {
- try {
- this.closeConnection();
- } catch (IOException exception) {
- protocolClient.getProtocolBridge().getLogger().exception("Failed to close connection to web server", var2);
- }
- }
- }
-
- /**
- * Closes the connection to the web server and releases resources.
- *
- * @return true if the connection was successfully closed, false if it was already closed.
- * @throws IOException If an I/O error occurs during closure.
- */
- public synchronized boolean closeConnection() throws IOException {
- if (!this.isConnected()) {
- return false;
- } else {
- clientToWebPipeline.disconnect();
-
- try {
- // Interrupt the receive thread
- this.receiveThread.interrupt();
-
- // Close streams and socket
- if (this.outputStream != null) {
- this.outputStream.close();
- }
-
- if (this.inputStream != null) {
- this.inputStream.close();
- }
-
- if (this.clientToWebServer != null) {
- this.clientToWebServer.close();
- }
- } finally {
- // Nullify references to help with garbage collection
- this.clientToWebServer = null;
- this.outputStream = null;
- this.inputStream = null;
- }
-
- return true;
- }
- }
-
-
-
-
-}
diff --git a/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java b/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java
index 3154455..1663acf 100644
--- a/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java
+++ b/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java
@@ -8,8 +8,8 @@ import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
-import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseCode;
-import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
+import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
+import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
import java.io.File;
import java.io.FileNotFoundException;
@@ -33,24 +33,21 @@ public abstract class ProtocolINSServer extends DefaultMethodsOverrider {
* The configuration manager for handling server configurations.
*/
private final ConfigurationManager configurationManager;
-
- /**
- * List of connected protocol clients.
- */
- @Getter
- private List
+ * The implementation should:
+ * This method is optional.
+ * This is the transport format used in responses and packets.
+ * Each record contains:
+ *
+ * Supported types:
+ *
+ *
+ *
+ * @param tln The top-level name.
+ * @param name The InfoName.
+ * @param sub The optional subname , may be {@code null}.
+ * @param type The INS record type being requested.
+ * @return A list of resolved INS records. May be empty if no record exists.
+ */
+ public abstract List
+ *
+ */
+public final class INSRecord implements Serializable {
+
+ public INSRecordType type;
+ public String value;
+ public int priority;
+ public int weight;
+ public int port;
+ public int ttl;
+
+ /**
+ * Creates an INS record object.
+ *
+ * @param type The INS record type.
+ * @param value The record’s data (IPv4, IPv6, hostname, text, etc.).
+ * @param priority MX / SRV priority value (ignored for other types).
+ * @param weight SRV weight (ignored for other types).
+ * @param port SRV port (ignored for other types).
+ * @param ttl Time-to-live for caching.
+ */
+ public INSRecord(INSRecordType type, String value, int priority, int weight, int port, int ttl) {
+ this.type = type;
+ this.value = value;
+ this.priority = priority;
+ this.weight = weight;
+ this.port = port;
+ this.ttl = ttl;
+ }
+
+ @Override
+ public String toString() {
+ return type + ":" + value;
+ }
+}
+
diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSRecordType.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSRecordType.java
new file mode 100644
index 0000000..b41551f
--- /dev/null
+++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSRecordType.java
@@ -0,0 +1,29 @@
+package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
+
+/**
+ * Represents INS record types for the INS protocol.
+ *
+ *
+ */
+public enum INSRecordType {
+ A,
+ AAAA,
+ CNAME,
+ TXT,
+ MX,
+ SRV,
+ NS,
+ PTR,
+ CAA
+}
diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseCode.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseCode.java
deleted file mode 100644
index ce84668..0000000
--- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseCode.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
-
-import lombok.Getter;
-
-import java.io.Serializable;
-
-/**
- * Enum representing various INS response codes and their descriptions.
- */
-public enum INSResponseCode implements Serializable {
- /**
- * General Responses
- */
- RESPONSE_NOT_REQUIRED(0, "Response code not required"),
- RESPONSE_INVALID_REQUEST(1, "Invalid request"),
-
- /**
- * Authentication Responses
- */
- RESPONSE_AUTH_SUCCESS(4, "Auth success"),
- RESPONSE_AUTH_FAILED(5, "Auth failed"),
-
- /**
- * InfoName Responses
- */
- RESPONSE_INFONAME_NAME_EXIST(100, "Infoname exist"),
- RESPONSE_INFONAME_NAME_NOT_EXIST(101, "Infoname does not exist"),
- RESPONSE_INFONAME_NAME_CREATED(105, "Infoname created"),
- RESPONSE_INFONAME_NAME_DELETED(106, "Infoname deleted"),
-
- /**
- * Top Level Name Responses
- */
- RESPONSE_INFONAME_TLN_EXIST(110, "TopLevelName exist"),
- RESPONSE_INFONAME_TLN_NOT_EXIST(111, "TopLevelName does not exist"),
- RESPONSE_INFONAME_TLN_CREATED(115, "TopLevelName created"),
- RESPONSE_INFONAME_TLN_DELETED(116, "TopLevelName deleted"),
-
- /**
- * Subname Responses
- */
- RESPONSE_INFONAME_SUBNAME_EXIST(120, "Subname exist"),
- RESPONSE_INFONAME_SUBNAME_NOT_EXIST(121, "Subname does not exist"),
- RESPONSE_INFONAME_SUBNAME_CREATED(125, "Subname created"),
- RESPONSE_INFONAME_SUBNAME_DELETED(126, "Subname deleted"),
-
- /**
- * Full InfoName Responses
- */
- RESPONSE_INFONAME_FULLY_EXIST(130, "Full Infoname exist"),
- RESPONSE_INFONAME_FULLY_NOT_EXIST(131, "Full Infoname does not exist");
-
- /**
- * The numeric code representing the INS response.
- */
- @Getter
- private final int code;
-
- /**
- * A brief description of the INS response code.
- */
- @Getter
- private final String description;
-
- /**
- * Constructor for INSResponseCode enum.
- *
- * @param code The numeric code of the response.
- * @param description A brief description of the response.
- */
- INSResponseCode(int code, String description) {
- this.code = code;
- this.description = description;
- }
-
- /**
- * Returns a string representation of the INS response code, including its code and description.
- *
- * @return a string representation of the INS response code.
- */
- @Override
- public String toString() {
- return "{code=" + code + ";description=" + description + "}";
- }
-}
diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseStatus.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseStatus.java
new file mode 100644
index 0000000..4242444
--- /dev/null
+++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/INSResponseStatus.java
@@ -0,0 +1,41 @@
+package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
+
+/**
+ * Defines the possible response states returned by the INS server.
+ */
+public enum INSResponseStatus {
+ /**
+ * Request succeeded and matching records were found.
+ */
+ OK,
+
+ /**
+ * No records exist for the queried TLN/name/sub/type combination.
+ */
+ NOT_FOUND,
+
+ /**
+ * The query was malformed or missing required parameters.
+ */
+ INVALID_REQUEST,
+
+ /**
+ * Internal server error occurred while resolving the request.
+ */
+ SERVER_ERROR,
+
+ /**
+ * Response is not required for the specific request type.
+ */
+ RESPONSE_NOT_REQUIRED,
+
+ /**
+ * Authentication failed.
+ */
+ RESPONSE_AUTH_FAILED,
+
+ /**
+ * Authentication succeeded.
+ */
+ RESPONSE_AUTH_SUCCESS
+}
diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/InfoName.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/InfoName.java
deleted file mode 100644
index 8366865..0000000
--- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/InfoName.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
-
-import lombok.Getter;
-import org.openautonomousconnection.protocol.ProtocolBridge;
-import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
-import org.openautonomousconnection.protocol.versions.ProtocolVersion;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Class representing a InfoName with its components such as subname, name, top-level name, path, query, fragment, and protocol.
- */
-public final class InfoName implements Serializable {
- /**
- * The subname of the InfoName (e.g., "sub" in "sub.example.com").
- */
- @Getter
- private final String subname;
-
- /**
- * The main name of the InfoName (e.g., "example" in "sub.example.com").
- */
- @Getter
- private final String name;
-
- /**
- * The top-level name of the InfoName (e.g., "com" in "sub.example.com").
- */
- @Getter
- private final String topLevelName;
-
- /**
- * The path component of the InfoName (e.g., "path/to/resource" in "example.com/path/to/resource").
- */
- @Getter
- private String path;
-
- /**
- * The query component of the InfoName (e.g., "key=value" in "example.com/path?key=value").
- */
- @Getter
- private String query;
-
- /**
- * The fragment component of the InfoName (e.g., "section1" in "example.com/path#section1").
- */
- @Getter
- private String fragment;
-
- /**
- * The protocol of the InfoName (e.g., "oac" in "oac://example.com").
- */
- @Getter
- private String protocol;
-
- /**
- * Constructs a InfoName object by parsing the provided full InfoName string.
- *
- * @param fullInfoName The full InfoName string to parse.
- * @throws IllegalArgumentException if the InfoName is invalid.
- */
- public InfoName(String fullInfoName) {
- // Remove protocol
- String infoNameWithPath = fullInfoName.contains("://") ? fullInfoName.split("://", 2)[1] : fullInfoName;
- this.protocol = fullInfoName.contains("://") ? fullInfoName.split("://", 2)[0] : "";
- if (this.protocol.endsWith("://"))
- this.protocol = this.protocol.substring(0, this.protocol.length() - "://".length());
-
- // Cut path
- String[] infoNamePartsAndPath = infoNameWithPath.split("/", 2);
-
- // Get host and full path
- String host = infoNamePartsAndPath[0];
- String fullPath = infoNamePartsAndPath.length > 1 ? "/" + infoNamePartsAndPath[1] : "";
-
- // Split InfoName in labels
- List