001package Torello.Browser; 002 003import javax.json.JsonObject; 004import java.util.function.Consumer; 005 006import Torello.Java.EXCC; 007import Torello.Java.StrPrint; 008 009 010/** 011 * <H2>Represents an Internal Java-Side Failure During WebSocket Communication</H2> 012 * 013 * This class is used to represent errors that arise during the execution of internal logic 014 * within the Java-based infrastructure responsible for interacting with the Chrome DevTools 015 * Protocol (CDP) over WebSockets. It is the conceptual opposite of {@link BrowserError}, which 016 * represents errors *reported by the browser itself*. 017 * 018 * <BR /><BR /> 019 * {@code RDPError} instances are thrown or passed downstream whenever an unexpected or 020 * invalid condition is detected by the Java-side handlers that process inbound or outbound 021 * messages on the WebSocket channel. 022 * 023 * <BR /><BR /> 024 * These are *not* errors originating from the browser. Instead, they usually reflect one of 025 * the following situations: 026 * 027 * <BR /><BR /><UL CLASS=JDUL> 028 * <LI>Failures inside message-processing logic (e.g., malformed or unrecognized JSON)</LI> 029 * <LI>Unchecked runtime exceptions triggered by handler code (e.g., NPE, casting failures)</LI> 030 * <LI>Unexpected conditions raised by the NeoVisionaries WebSocket implementation</LI> 031 * <LI>Structural violations in expected CDP response formats</LI> 032 * </UL> 033 * 034 * <BR />{@code RDPError} objects can optionally include: 035 * 036 * <BR /><BR /><UL CLASS=JDUL> 037 * <LI>A textual message describing the failure</LI> 038 * <LI>The raw {@code JsonObject} that caused the error (if applicable)</LI> 039 * <LI>A {@code Throwable} that was caught and wrapped</LI> 040 * </UL> 041 * 042 * <BR /><BR /><B CLASS=JDDescLabel2>Causing these Errors:</B> 043 * <BR /> 044 * All instantiations of this class occur inside one of the four internal infrastructure 045 * classes: 046 * 047 * <BR /><BR /><UL CLASS=JDUL> 048 * 049 * <LI> <B><CODE><A HREF='hilite-files/HandleScriptResponse.java.html'> 050 * HandleScriptResponse</A></CODE></B> 051 * </LI> 052 * 053 * <LI> <B><CODE><A HREF='hilite-files/HandleDispatch.java.html'> 054 * HandleDispatch</A></CODE></B> 055 * </LI> 056 * 057 * <LI><B><CODE><A HREF='hilite-files/HandleEvent.java.html'>HandleEvent</A></CODE></B></LI> 058 * <LI><B><CODE><A HREF='hilite-files/WSAdapter.java.html'>WSAdapter</A></CODE></B></LI> 059 * </UL> 060 * 061 * <BR /> 062 * Because these errors reflect misbehavior or malformation in Java-managed logic, they should 063 * never be ignored. They often signal bugs in parsing logic, protocol desynchronization, or 064 * incorrect assumptions in command/response handling. 065 * 066 * <BR /><BR /><BR /><B CLASS=JDDescLabel2>Registering a Handler:</B> 067 * <BR /> 068 * To receive instances of this error class, a handler must be registered at the time you create 069 * your {@link WebSocketSender} using one of the {@code createSender(...)} methods found in either 070 * {@link BrowserConn#createSender BrowserConn} or {@link PageConn#createSender PageConn}. These 071 * methods allow you to provide lambda handlers or consumer functions for error callbacks. Without 072 * explicitly setting a handler for this error type, you will never see these errors—they will be 073 * silently discarded or ignored by the internal infrastructure. 074 * 075 * <BR /><BR /> 076 * Each of the three CDP error/response types — {@link RDPError}, {@link BrowserError}, and 077 * {@link BrowserEvent} — has its own dedicated handler. These are supplied as {@code Consumer} 078 * arguments to {@code createSender(...)}, and any logic you wish to perform in response to these 079 * events must be defined there. The {@code WebSocketSender} will invoke these handlers 080 * automatically whenever it receives a message of the corresponding kind. 081 */ 082public final class RDPError 083 implements java.io.Serializable, Comparable<RDPError> 084{ 085 /** <EMBED CLASS=external-html DATA-FILE-ID=SVUID> */ 086 protected static final long serialVersionUID = 1; 087 088 089 // ******************************************************************************************** 090 // ******************************************************************************************** 091 // Public, Final Fields 092 // ******************************************************************************************** 093 // ******************************************************************************************** 094 095 096 /** 097 * A descriptive message explaining the nature of the internal error. 098 * 099 * <BR /><BR /> 100 * This string is almost always provided by the handler logic itself to contextualize what went 101 * wrong — e.g., "Unrecognized ID field", "Unexpected type in CDP response", or "Missing 102 * 'method' property in event dispatch." 103 */ 104 public final String message; 105 106 /** 107 * The underlying exception or cause that led to this RDPError. 108 * 109 * <BR /><BR /> 110 * This may include {@code NullPointerException}, {@code ClassCastException}, or any 111 * other unchecked exception that occurred during handler execution. It may be {@code null} 112 * if the error was raised directly without an underlying Throwable. 113 */ 114 public final Throwable cause; 115 116 /** 117 * The raw {@link JsonObject} that was being processed at the time the error occurred. 118 * 119 * <BR /><BR /> 120 * This field is useful for debugging. It often contains the browser's CDP response that 121 * the Java code failed to parse or recognize. It may be {@code null} if the failure was 122 * unrelated to message content (e.g., a runtime exception). 123 */ 124 public final JsonObject jo; 125 126 127 // ******************************************************************************************** 128 // ******************************************************************************************** 129 // Constructors 130 // ******************************************************************************************** 131 // ******************************************************************************************** 132 133 134 RDPError(String message) 135 { 136 if (message == null) System.err.println("Input to Error has a null message"); 137 138 this.message = message; 139 this.jo = null; 140 this.cause = null; 141 } 142 143 RDPError(final String message, final JsonObject jo) 144 { 145 if (message == null) 146 System.err.println("Input to RDPError Constructor has a null message"); 147 148 if (jo == null) System.err.println 149 ("Input to RDPError Constructor has a null JsonObject-Parameter"); 150 151 this.message = message; 152 this.jo = jo; 153 this.cause = null; 154 } 155 156 RDPError(final String message, final Throwable cause) 157 { 158 if (message == null) System.err.println 159 ("Input to RDPError Constructor has a null message"); 160 161 if (cause == null) System.err.println 162 ("Input to RDPError Constructor has a null Throwable-Parameter"); 163 164 this.message = message; 165 this.cause = cause; 166 this.jo = null; 167 } 168 169 RDPError(String message, JsonObject jo, Throwable cause) 170 { 171 if (message == null) System.err.println 172 ("Input to RDPError Constructor has a null message"); 173 174 if (jo == null) System.err.println 175 ("Input to RDPError Constructor has a null JsonObject-Parameter"); 176 177 if (cause == null) System.err.println 178 ("Input to RDPError Constructor has a null Throwable-Parameter"); 179 180 this.message = message; 181 this.jo = jo; 182 this.cause = cause; 183 } 184 185 186 // ******************************************************************************************** 187 // ******************************************************************************************** 188 // java.lang.Object, Comparable, Clonable 189 // ******************************************************************************************** 190 // ******************************************************************************************** 191 192 193 @Override 194 public String toString() 195 { 196 final String jsonStr = (jo == null) 197 ? " JSON: NULL" 198 : (" JSON: \n" + PrintUtil.json2(jo)); 199 200 final String causeStr = (cause == null) 201 ? " Cause Throwable: NULL" 202 : (" Cause: \n" + EXCC.toString(cause)); 203 204 return 205 "RDPError Object\n" + 206 "{\n" + 207 " Message: " + message + '\n' + 208 jsonStr + '\n' + 209 causeStr + '\n' + 210 '}'; 211 } 212 213 @Override 214 public int hashCode() 215 { return message.hashCode(); } 216 217 @Override 218 public boolean equals(Object o) 219 { 220 if (this == o) return true; 221 if (o == null) return false; 222 223 if (this.getClass() != o.getClass()) return false; 224 225 final RDPError error = (RDPError) o; 226 227 return (message.equals(error.message)); 228 } 229 230 @Override 231 public int compareTo(RDPError error) 232 { return this.message.compareTo(error.message); } 233}