001package Torello.Browser;
002
003import java.util.*;
004import javax.json.*;
005import javax.json.stream.*;
006import java.io.*;
007
008import java.lang.reflect.Method;
009import java.lang.reflect.Parameter;
010import java.util.function.Function;
011
012import Torello.Java.Additional.*;
013import Torello.Java.JSON.*;
014
015import static Torello.Java.JSON.JFlag.*;
016
017import Torello.Java.StrCmpr;
018import Torello.JavaDoc.StaticFunctional;
019import Torello.JavaDoc.JDHeaderBackgroundImg;
020import Torello.JavaDoc.Excuse;
021
022/**
023 * <SPAN CLASS=COPIEDJDK><B>Provides access to log entries.</B></SPAN>
024 * 
025 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
026 */
027@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
028@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
029public class Log
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private Log () { }
040
041    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
042    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
043    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
044    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
045
046    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
047    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
048    // offically, two empty-vectors.  One for String's, and the other for Classes.
049
050    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
051    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
052
053    static
054    {
055        for (Method m : Log.class.getMethods())
056        {
057            // This doesn't work!  The parameter names are all "arg0" ... "argN"
058            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
059            //
060            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
061
062            Vector<Class<?>> parameterTypesList = new Vector<>();
063        
064            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
065
066            parameterTypes.put(
067                m.getName(),
068                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
069            );
070        }
071    }
072
073    static
074    {
075        Vector<String> v = null;
076
077        parameterNames.put("clear", EMPTY_VEC_STR);
078
079        parameterNames.put("disable", EMPTY_VEC_STR);
080
081        parameterNames.put("enable", EMPTY_VEC_STR);
082
083        v = new Vector<String>(1);
084        parameterNames.put("startViolationsReport", v);
085        Collections.addAll(v, new String[]
086        { "config", });
087
088        parameterNames.put("stopViolationsReport", EMPTY_VEC_STR);
089    }
090
091
092    // ********************************************************************************************
093    // ********************************************************************************************
094    // Types - Static Inner Classes
095    // ********************************************************************************************
096    // ********************************************************************************************
097
098    /** Log entry. */
099    public static class LogEntry
100        extends BaseType
101        implements java.io.Serializable
102    {
103        /** For Object Serialization.  java.io.Serializable */
104        protected static final long serialVersionUID = 1;
105        
106        public boolean[] optionals()
107        { return new boolean[] { false, false, false, true, false, true, true, true, true, true, true, }; }
108        
109        /** Log entry source. */
110        public final String source;
111        
112        /** Log entry severity. */
113        public final String level;
114        
115        /** Logged text. */
116        public final String text;
117        
118        /**
119         * <CODE>[No Description Provided by Google]</CODE>
120         * <BR />
121         * <BR /><B>OPTIONAL</B>
122         */
123        public final String category;
124        
125        /** Timestamp when this entry was added. */
126        public final Number timestamp;
127        
128        /**
129         * URL of the resource if known.
130         * <BR />
131         * <BR /><B>OPTIONAL</B>
132         */
133        public final String url;
134        
135        /**
136         * Line number in the resource.
137         * <BR />
138         * <BR /><B>OPTIONAL</B>
139         */
140        public final Integer lineNumber;
141        
142        /**
143         * JavaScript stack trace.
144         * <BR />
145         * <BR /><B>OPTIONAL</B>
146         */
147        public final RunTime.StackTrace stackTrace;
148        
149        /**
150         * Identifier of the network request associated with this entry.
151         * <BR />
152         * <BR /><B>OPTIONAL</B>
153         */
154        public final String networkRequestId;
155        
156        /**
157         * Identifier of the worker associated with this entry.
158         * <BR />
159         * <BR /><B>OPTIONAL</B>
160         */
161        public final String workerId;
162        
163        /**
164         * Call arguments.
165         * <BR />
166         * <BR /><B>OPTIONAL</B>
167         */
168        public final RunTime.RemoteObject[] args;
169        
170        /**
171         * Constructor
172         *
173         * @param source Log entry source.
174         * <BR />Acceptable Values: ["xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "recommendation", "other"]
175         * 
176         * @param level Log entry severity.
177         * <BR />Acceptable Values: ["verbose", "info", "warning", "error"]
178         * 
179         * @param text Logged text.
180         * 
181         * @param category -
182         * <BR />Acceptable Values: ["cors"]
183         * <BR /><B>OPTIONAL</B>
184         * 
185         * @param timestamp Timestamp when this entry was added.
186         * 
187         * @param url URL of the resource if known.
188         * <BR /><B>OPTIONAL</B>
189         * 
190         * @param lineNumber Line number in the resource.
191         * <BR /><B>OPTIONAL</B>
192         * 
193         * @param stackTrace JavaScript stack trace.
194         * <BR /><B>OPTIONAL</B>
195         * 
196         * @param networkRequestId Identifier of the network request associated with this entry.
197         * <BR /><B>OPTIONAL</B>
198         * 
199         * @param workerId Identifier of the worker associated with this entry.
200         * <BR /><B>OPTIONAL</B>
201         * 
202         * @param args Call arguments.
203         * <BR /><B>OPTIONAL</B>
204         */
205        public LogEntry(
206                String source, String level, String text, String category, Number timestamp, 
207                String url, Integer lineNumber, RunTime.StackTrace stackTrace, 
208                String networkRequestId, String workerId, RunTime.RemoteObject[] args
209            )
210        {
211            // Exception-Check(s) to ensure that if any parameters which are not declared as
212            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
213            
214            if (source == null)    BRDPC.throwNPE("source");
215            if (level == null)     BRDPC.throwNPE("level");
216            if (text == null)      BRDPC.throwNPE("text");
217            if (timestamp == null) BRDPC.throwNPE("timestamp");
218            
219            // Exception-Check(s) to ensure that if any parameters which must adhere to a
220            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
221            
222            BRDPC.checkIAE(
223                "source", source,
224                "xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "recommendation", "other"
225            );
226            BRDPC.checkIAE(
227                "level", level,
228                "verbose", "info", "warning", "error"
229            );
230            BRDPC.checkIAE(
231                "category", category,
232                "cors"
233            );
234            
235            this.source            = source;
236            this.level             = level;
237            this.text              = text;
238            this.category          = category;
239            this.timestamp         = timestamp;
240            this.url               = url;
241            this.lineNumber        = lineNumber;
242            this.stackTrace        = stackTrace;
243            this.networkRequestId  = networkRequestId;
244            this.workerId          = workerId;
245            this.args              = args;
246        }
247        
248        /**
249         * JSON Object Constructor
250         * @param jo A Json-Object having data about an instance of {@code 'LogEntry'}.
251         */
252        public LogEntry (JsonObject jo)
253        {
254            this.source            = ReadJSON.getString(jo, "source", false, true);
255            this.level             = ReadJSON.getString(jo, "level", false, true);
256            this.text              = ReadJSON.getString(jo, "text", false, true);
257            this.category          = ReadJSON.getString(jo, "category", true, false);
258            this.timestamp         = ReadNumberJSON.get(jo, "timestamp", false, true);
259            this.url               = ReadJSON.getString(jo, "url", true, false);
260            this.lineNumber        = ReadBoxedJSON.getInteger(jo, "lineNumber", true);
261            this.stackTrace        = ReadJSON.getObject(jo, "stackTrace", RunTime.StackTrace.class, true, false);
262            this.networkRequestId  = ReadJSON.getString(jo, "networkRequestId", true, false);
263            this.workerId          = ReadJSON.getString(jo, "workerId", true, false);
264            this.args = (jo.getJsonArray("args") == null)
265                ? null
266                : ReadArrJSON.DimN.objArr(jo.getJsonArray("args"), null, 0, RunTime.RemoteObject[].class);
267        
268        }
269        
270        
271        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
272        public boolean equals(Object other)
273        {
274            if (other == null)                       return false;
275            if (other.getClass() != this.getClass()) return false;
276        
277            LogEntry o = (LogEntry) other;
278        
279            return
280                    Objects.equals(this.source, o.source)
281                &&  Objects.equals(this.level, o.level)
282                &&  Objects.equals(this.text, o.text)
283                &&  Objects.equals(this.category, o.category)
284                &&  Objects.equals(this.timestamp, o.timestamp)
285                &&  Objects.equals(this.url, o.url)
286                &&  Objects.equals(this.lineNumber, o.lineNumber)
287                &&  Objects.equals(this.stackTrace, o.stackTrace)
288                &&  Objects.equals(this.networkRequestId, o.networkRequestId)
289                &&  Objects.equals(this.workerId, o.workerId)
290                &&  Arrays.deepEquals(this.args, o.args);
291        }
292        
293        /** Generates a Hash-Code for {@code 'this'} instance */
294        public int hashCode()
295        {
296            return
297                    Objects.hashCode(this.source)
298                +   Objects.hashCode(this.level)
299                +   Objects.hashCode(this.text)
300                +   Objects.hashCode(this.category)
301                +   Objects.hashCode(this.timestamp)
302                +   Objects.hashCode(this.url)
303                +   Objects.hashCode(this.lineNumber)
304                +   this.stackTrace.hashCode()
305                +   Objects.hashCode(this.networkRequestId)
306                +   Objects.hashCode(this.workerId)
307                +   Arrays.deepHashCode(this.args);
308        }
309    }
310    
311    /** Violation configuration setting. */
312    public static class ViolationSetting
313        extends BaseType
314        implements java.io.Serializable
315    {
316        /** For Object Serialization.  java.io.Serializable */
317        protected static final long serialVersionUID = 1;
318        
319        public boolean[] optionals()
320        { return new boolean[] { false, false, }; }
321        
322        /** Violation type. */
323        public final String name;
324        
325        /** Time threshold to trigger upon. */
326        public final Number threshold;
327        
328        /**
329         * Constructor
330         *
331         * @param name Violation type.
332         * <BR />Acceptable Values: ["longTask", "longLayout", "blockedEvent", "blockedParser", "discouragedAPIUse", "handler", "recurringHandler"]
333         * 
334         * @param threshold Time threshold to trigger upon.
335         */
336        public ViolationSetting(String name, Number threshold)
337        {
338            // Exception-Check(s) to ensure that if any parameters which are not declared as
339            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
340            
341            if (name == null)      BRDPC.throwNPE("name");
342            if (threshold == null) BRDPC.throwNPE("threshold");
343            
344            // Exception-Check(s) to ensure that if any parameters which must adhere to a
345            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
346            
347            BRDPC.checkIAE(
348                "name", name,
349                "longTask", "longLayout", "blockedEvent", "blockedParser", "discouragedAPIUse", "handler", "recurringHandler"
350            );
351            
352            this.name       = name;
353            this.threshold  = threshold;
354        }
355        
356        /**
357         * JSON Object Constructor
358         * @param jo A Json-Object having data about an instance of {@code 'ViolationSetting'}.
359         */
360        public ViolationSetting (JsonObject jo)
361        {
362            this.name       = ReadJSON.getString(jo, "name", false, true);
363            this.threshold  = ReadNumberJSON.get(jo, "threshold", false, true);
364        }
365        
366        
367        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
368        public boolean equals(Object other)
369        {
370            if (other == null)                       return false;
371            if (other.getClass() != this.getClass()) return false;
372        
373            ViolationSetting o = (ViolationSetting) other;
374        
375            return
376                    Objects.equals(this.name, o.name)
377                &&  Objects.equals(this.threshold, o.threshold);
378        }
379        
380        /** Generates a Hash-Code for {@code 'this'} instance */
381        public int hashCode()
382        {
383            return
384                    Objects.hashCode(this.name)
385                +   Objects.hashCode(this.threshold);
386        }
387    }
388    
389    /** Issued when new message was logged. */
390    public static class entryAdded
391        extends BrowserEvent
392        implements java.io.Serializable
393    {
394        /** For Object Serialization.  java.io.Serializable */
395        protected static final long serialVersionUID = 1;
396        
397        public boolean[] optionals()
398        { return new boolean[] { false, }; }
399        
400        /** The entry. */
401        public final Log.LogEntry entry;
402        
403        /**
404         * Constructor
405         *
406         * @param entry The entry.
407         */
408        public entryAdded(Log.LogEntry entry)
409        {
410            super("Log", "entryAdded", 1);
411            
412            // Exception-Check(s) to ensure that if any parameters which are not declared as
413            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
414            
415            if (entry == null) BRDPC.throwNPE("entry");
416            
417            this.entry  = entry;
418        }
419        
420        /**
421         * JSON Object Constructor
422         * @param jo A Json-Object having data about an instance of {@code 'entryAdded'}.
423         */
424        public entryAdded (JsonObject jo)
425        {
426            super("Log", "entryAdded", 1);
427        
428            this.entry  = ReadJSON.getObject(jo, "entry", Log.LogEntry.class, false, true);
429        }
430        
431        
432        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
433        public boolean equals(Object other)
434        {
435            if (other == null)                       return false;
436            if (other.getClass() != this.getClass()) return false;
437        
438            entryAdded o = (entryAdded) other;
439        
440            return
441                    Objects.equals(this.entry, o.entry);
442        }
443        
444        /** Generates a Hash-Code for {@code 'this'} instance */
445        public int hashCode()
446        {
447            return
448                    this.entry.hashCode();
449        }
450    }
451    
452    
453    // Counter for keeping the WebSocket Request ID's distinct.
454    private static int counter = 1;
455    
456    /**
457     * Clears the log.
458     * 
459     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
460     * {@link Ret0}&gt;</CODE>
461     *
462     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
463     * browser receives the invocation-request.
464     *
465     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
466     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
467     * {@code >} to ensure the Browser Function has run to completion.
468     */
469    public static Script<String, JsonObject, Ret0> clear()
470    {
471        final int          webSocketID = 28000000 + counter++;
472        final boolean[]    optionals   = new boolean[0];
473        
474        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
475        String requestJSON = WriteJSON.get(
476            parameterTypes.get("clear"),
477            parameterNames.get("clear"),
478            optionals, webSocketID,
479            "Log.clear"
480        );
481        
482        // This Remote Command does not have a Return-Value.
483        return new Script<>
484            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
485    }
486    
487    /**
488     * Disables log domain, prevents further log entries from being reported to the client.
489     * 
490     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
491     * {@link Ret0}&gt;</CODE>
492     *
493     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
494     * browser receives the invocation-request.
495     *
496     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
497     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
498     * {@code >} to ensure the Browser Function has run to completion.
499     */
500    public static Script<String, JsonObject, Ret0> disable()
501    {
502        final int          webSocketID = 28001000 + counter++;
503        final boolean[]    optionals   = new boolean[0];
504        
505        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
506        String requestJSON = WriteJSON.get(
507            parameterTypes.get("disable"),
508            parameterNames.get("disable"),
509            optionals, webSocketID,
510            "Log.disable"
511        );
512        
513        // This Remote Command does not have a Return-Value.
514        return new Script<>
515            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
516    }
517    
518    /**
519     * Enables log domain, sends the entries collected so far to the client by means of the
520     * <CODE>entryAdded</CODE> notification.
521     * 
522     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
523     * {@link Ret0}&gt;</CODE>
524     *
525     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
526     * browser receives the invocation-request.
527     *
528     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
529     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
530     * {@code >} to ensure the Browser Function has run to completion.
531     */
532    public static Script<String, JsonObject, Ret0> enable()
533    {
534        final int          webSocketID = 28002000 + counter++;
535        final boolean[]    optionals   = new boolean[0];
536        
537        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
538        String requestJSON = WriteJSON.get(
539            parameterTypes.get("enable"),
540            parameterNames.get("enable"),
541            optionals, webSocketID,
542            "Log.enable"
543        );
544        
545        // This Remote Command does not have a Return-Value.
546        return new Script<>
547            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
548    }
549    
550    /**
551     * start violation reporting.
552     * 
553     * @param config Configuration for violations.
554     * 
555     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
556     * {@link Ret0}&gt;</CODE>
557     *
558     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
559     * browser receives the invocation-request.
560     *
561     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
562     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
563     * {@code >} to ensure the Browser Function has run to completion.
564     */
565    public static Script<String, JsonObject, Ret0> startViolationsReport
566        (Log.ViolationSetting[] config)
567    {
568        // Exception-Check(s) to ensure that if any parameters which are not declared as
569        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
570        
571        if (config == null) BRDPC.throwNPE("config");
572        
573        final int       webSocketID = 28003000 + counter++;
574        final boolean[] optionals   = { false, };
575        
576        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
577        String requestJSON = WriteJSON.get(
578            parameterTypes.get("startViolationsReport"),
579            parameterNames.get("startViolationsReport"),
580            optionals, webSocketID,
581            "Log.startViolationsReport",
582            (Object) config
583        );
584        
585        // This Remote Command does not have a Return-Value.
586        return new Script<>
587            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
588    }
589    
590    /**
591     * Stop violation reporting.
592     * 
593     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
594     * {@link Ret0}&gt;</CODE>
595     *
596     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
597     * browser receives the invocation-request.
598     *
599     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
600     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
601     * {@code >} to ensure the Browser Function has run to completion.
602     */
603    public static Script<String, JsonObject, Ret0> stopViolationsReport()
604    {
605        final int          webSocketID = 28004000 + counter++;
606        final boolean[]    optionals   = new boolean[0];
607        
608        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
609        String requestJSON = WriteJSON.get(
610            parameterTypes.get("stopViolationsReport"),
611            parameterNames.get("stopViolationsReport"),
612            optionals, webSocketID,
613            "Log.stopViolationsReport"
614        );
615        
616        // This Remote Command does not have a Return-Value.
617        return new Script<>
618            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
619    }
620    
621}