001package Torello.Browser.BrowserAPI;
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.Browser.BrowserEvent;
013import Torello.Browser.JavaScriptAPI.*;
014import Torello.Browser.helper.*;
015
016import Torello.Java.Additional.*;
017import Torello.Java.JSON.*;
018
019import static Torello.Java.JSON.JFlag.*;
020
021import Torello.Java.StrCmpr;
022import Torello.JavaDoc.StaticFunctional;
023import Torello.JavaDoc.JDHeaderBackgroundImg;
024import Torello.JavaDoc.Excuse;
025
026/**
027 * <SPAN CLASS=COPIEDJDK><B>Provides access to log entries.</B></SPAN>
028 * 
029 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
030 */
031@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
032@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
033public class Log
034{
035    // ********************************************************************************************
036    // ********************************************************************************************
037    // Class Header Stuff
038    // ********************************************************************************************
039    // ********************************************************************************************
040
041
042    // No Pubic Constructors
043    private Log () { }
044
045    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
046    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
047    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
048    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
049
050    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
051    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
052    // offically, two empty-vectors.  One for String's, and the other for Classes.
053
054    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
055    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
056
057    static
058    {
059        for (Method m : Log.class.getMethods())
060        {
061            // This doesn't work!  The parameter names are all "arg0" ... "argN"
062            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
063            //
064            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
065
066            Vector<Class<?>> parameterTypesList = new Vector<>();
067        
068            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
069
070            parameterTypes.put(
071                m.getName(),
072                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
073            );
074        }
075    }
076
077    static
078    {
079        Vector<String> v = null;
080
081        parameterNames.put("clear", EMPTY_VEC_STR);
082
083        parameterNames.put("disable", EMPTY_VEC_STR);
084
085        parameterNames.put("enable", EMPTY_VEC_STR);
086
087        v = new Vector<String>(1);
088        parameterNames.put("startViolationsReport", v);
089        Collections.addAll(v, new String[]
090        { "config", });
091
092        parameterNames.put("stopViolationsReport", EMPTY_VEC_STR);
093    }
094
095
096    // ********************************************************************************************
097    // ********************************************************************************************
098    // Types - Static Inner Classes
099    // ********************************************************************************************
100    // ********************************************************************************************
101
102    /** Log entry. */
103    public static class LogEntry
104        extends BaseType
105        implements java.io.Serializable
106    {
107        /** For Object Serialization.  java.io.Serializable */
108        protected static final long serialVersionUID = 1;
109        
110        public boolean[] optionals()
111        { return new boolean[] { false, false, false, true, false, true, true, true, true, true, true, }; }
112        
113        /** Log entry source. */
114        public final String source;
115        
116        /** Log entry severity. */
117        public final String level;
118        
119        /** Logged text. */
120        public final String text;
121        
122        /**
123         * <CODE>[No Description Provided by Google]</CODE>
124         * <BR /><B CLASS=Opt>OPTIONAL</B>
125         */
126        public final String category;
127        
128        /** Timestamp when this entry was added. */
129        public final Number timestamp;
130        
131        /**
132         * URL of the resource if known.
133         * <BR /><B CLASS=Opt>OPTIONAL</B>
134         */
135        public final String url;
136        
137        /**
138         * Line number in the resource.
139         * <BR /><B CLASS=Opt>OPTIONAL</B>
140         */
141        public final Integer lineNumber;
142        
143        /**
144         * JavaScript stack trace.
145         * <BR /><B CLASS=Opt>OPTIONAL</B>
146         */
147        public final RunTime.StackTrace stackTrace;
148        
149        /**
150         * Identifier of the network request associated with this entry.
151         * <BR /><B CLASS=Opt>OPTIONAL</B>
152         */
153        public final String networkRequestId;
154        
155        /**
156         * Identifier of the worker associated with this entry.
157         * <BR /><B CLASS=Opt>OPTIONAL</B>
158         */
159        public final String workerId;
160        
161        /**
162         * Call arguments.
163         * <BR /><B CLASS=Opt>OPTIONAL</B>
164         */
165        public final RunTime.RemoteObject[] args;
166        
167        /**
168         * Constructor
169         *
170         * @param source Log entry source.
171         * <BR />Acceptable Values: ["xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "recommendation", "other"]
172         * 
173         * @param level Log entry severity.
174         * <BR />Acceptable Values: ["verbose", "info", "warning", "error"]
175         * 
176         * @param text Logged text.
177         * 
178         * @param category -
179         * <BR />Acceptable Values: ["cors"]
180         * <BR /><B CLASS=Opt>OPTIONAL</B>
181         * 
182         * @param timestamp Timestamp when this entry was added.
183         * 
184         * @param url URL of the resource if known.
185         * <BR /><B CLASS=Opt>OPTIONAL</B>
186         * 
187         * @param lineNumber Line number in the resource.
188         * <BR /><B CLASS=Opt>OPTIONAL</B>
189         * 
190         * @param stackTrace JavaScript stack trace.
191         * <BR /><B CLASS=Opt>OPTIONAL</B>
192         * 
193         * @param networkRequestId Identifier of the network request associated with this entry.
194         * <BR /><B CLASS=Opt>OPTIONAL</B>
195         * 
196         * @param workerId Identifier of the worker associated with this entry.
197         * <BR /><B CLASS=Opt>OPTIONAL</B>
198         * 
199         * @param args Call arguments.
200         * <BR /><B CLASS=Opt>OPTIONAL</B>
201         */
202        public LogEntry(
203                String source, String level, String text, String category, Number timestamp, 
204                String url, Integer lineNumber, RunTime.StackTrace stackTrace, 
205                String networkRequestId, String workerId, RunTime.RemoteObject[] args
206            )
207        {
208            // Exception-Check(s) to ensure that if any parameters which are not declared as
209            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
210            
211            if (source == null)    THROWS.throwNPE("source");
212            if (level == null)     THROWS.throwNPE("level");
213            if (text == null)      THROWS.throwNPE("text");
214            if (timestamp == null) THROWS.throwNPE("timestamp");
215            
216            // Exception-Check(s) to ensure that if any parameters which must adhere to a
217            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
218            
219            THROWS.checkIAE(
220                "source", source,
221                "xml", "javascript", "network", "storage", "appcache", "rendering", "security", "deprecation", "worker", "violation", "intervention", "recommendation", "other"
222            );
223            THROWS.checkIAE(
224                "level", level,
225                "verbose", "info", "warning", "error"
226            );
227            THROWS.checkIAE(
228                "category", category,
229                "cors"
230            );
231            
232            this.source            = source;
233            this.level             = level;
234            this.text              = text;
235            this.category          = category;
236            this.timestamp         = timestamp;
237            this.url               = url;
238            this.lineNumber        = lineNumber;
239            this.stackTrace        = stackTrace;
240            this.networkRequestId  = networkRequestId;
241            this.workerId          = workerId;
242            this.args              = args;
243        }
244        
245        /**
246         * JSON Object Constructor
247         * @param jo A Json-Object having data about an instance of {@code 'LogEntry'}.
248         */
249        public LogEntry (JsonObject jo)
250        {
251            this.source            = ReadJSON.getString(jo, "source", false, true);
252            this.level             = ReadJSON.getString(jo, "level", false, true);
253            this.text              = ReadJSON.getString(jo, "text", false, true);
254            this.category          = ReadJSON.getString(jo, "category", true, false);
255            this.timestamp         = ReadNumberJSON.get(jo, "timestamp", false, true);
256            this.url               = ReadJSON.getString(jo, "url", true, false);
257            this.lineNumber        = ReadBoxedJSON.getInteger(jo, "lineNumber", true);
258            this.stackTrace        = ReadJSON.getObject(jo, "stackTrace", RunTime.StackTrace.class, true, false);
259            this.networkRequestId  = ReadJSON.getString(jo, "networkRequestId", true, false);
260            this.workerId          = ReadJSON.getString(jo, "workerId", true, false);
261            this.args = (jo.getJsonArray("args") == null)
262                ? null
263                : RJArrIntoStream.objArr(jo.getJsonArray("args"), null, 0, RunTime.RemoteObject.class).toArray(RunTime.RemoteObject[]::new);
264        
265        }
266        
267        
268        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
269        public boolean equals(Object other)
270        {
271            if (this == other)                       return true;
272            if (other == null)                       return false;
273            if (other.getClass() != this.getClass()) return false;
274        
275            LogEntry o = (LogEntry) other;
276        
277            return
278                    Objects.equals(this.source, o.source)
279                &&  Objects.equals(this.level, o.level)
280                &&  Objects.equals(this.text, o.text)
281                &&  Objects.equals(this.category, o.category)
282                &&  Objects.equals(this.timestamp, o.timestamp)
283                &&  Objects.equals(this.url, o.url)
284                &&  Objects.equals(this.lineNumber, o.lineNumber)
285                &&  Objects.equals(this.stackTrace, o.stackTrace)
286                &&  Objects.equals(this.networkRequestId, o.networkRequestId)
287                &&  Objects.equals(this.workerId, o.workerId)
288                &&  Arrays.deepEquals(this.args, o.args);
289        }
290        
291        /** Generates a Hash-Code for {@code 'this'} instance */
292        public int hashCode()
293        {
294            return
295                    Objects.hashCode(this.source)
296                +   Objects.hashCode(this.level)
297                +   Objects.hashCode(this.text)
298                +   Objects.hashCode(this.category)
299                +   Objects.hashCode(this.timestamp)
300                +   Objects.hashCode(this.url)
301                +   Objects.hashCode(this.lineNumber)
302                +   this.stackTrace.hashCode()
303                +   Objects.hashCode(this.networkRequestId)
304                +   Objects.hashCode(this.workerId)
305                +   Arrays.deepHashCode(this.args);
306        }
307    }
308    
309    /** Violation configuration setting. */
310    public static class ViolationSetting
311        extends BaseType
312        implements java.io.Serializable
313    {
314        /** For Object Serialization.  java.io.Serializable */
315        protected static final long serialVersionUID = 1;
316        
317        public boolean[] optionals()
318        { return new boolean[] { false, false, }; }
319        
320        /** Violation type. */
321        public final String name;
322        
323        /** Time threshold to trigger upon. */
324        public final Number threshold;
325        
326        /**
327         * Constructor
328         *
329         * @param name Violation type.
330         * <BR />Acceptable Values: ["longTask", "longLayout", "blockedEvent", "blockedParser", "discouragedAPIUse", "handler", "recurringHandler"]
331         * 
332         * @param threshold Time threshold to trigger upon.
333         */
334        public ViolationSetting(String name, Number threshold)
335        {
336            // Exception-Check(s) to ensure that if any parameters which are not declared as
337            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
338            
339            if (name == null)      THROWS.throwNPE("name");
340            if (threshold == null) THROWS.throwNPE("threshold");
341            
342            // Exception-Check(s) to ensure that if any parameters which must adhere to a
343            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
344            
345            THROWS.checkIAE(
346                "name", name,
347                "longTask", "longLayout", "blockedEvent", "blockedParser", "discouragedAPIUse", "handler", "recurringHandler"
348            );
349            
350            this.name       = name;
351            this.threshold  = threshold;
352        }
353        
354        /**
355         * JSON Object Constructor
356         * @param jo A Json-Object having data about an instance of {@code 'ViolationSetting'}.
357         */
358        public ViolationSetting (JsonObject jo)
359        {
360            this.name       = ReadJSON.getString(jo, "name", false, true);
361            this.threshold  = ReadNumberJSON.get(jo, "threshold", false, true);
362        }
363        
364        
365        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
366        public boolean equals(Object other)
367        {
368            if (this == other)                       return true;
369            if (other == null)                       return false;
370            if (other.getClass() != this.getClass()) return false;
371        
372            ViolationSetting o = (ViolationSetting) other;
373        
374            return
375                    Objects.equals(this.name, o.name)
376                &&  Objects.equals(this.threshold, o.threshold);
377        }
378        
379        /** Generates a Hash-Code for {@code 'this'} instance */
380        public int hashCode()
381        {
382            return
383                    Objects.hashCode(this.name)
384                +   Objects.hashCode(this.threshold);
385        }
386    }
387    
388    /** Issued when new message was logged. */
389    public static class entryAdded
390        extends BrowserEvent
391        implements java.io.Serializable
392    {
393        /** For Object Serialization.  java.io.Serializable */
394        protected static final long serialVersionUID = 1;
395        
396        public boolean[] optionals()
397        { return new boolean[] { false, }; }
398        
399        /** The entry. */
400        public final Log.LogEntry entry;
401        
402        /**
403         * Constructor
404         *
405         * @param entry The entry.
406         */
407        public entryAdded(Log.LogEntry entry)
408        {
409            super("Log", "entryAdded", 1);
410            
411            // Exception-Check(s) to ensure that if any parameters which are not declared as
412            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
413            
414            if (entry == null) THROWS.throwNPE("entry");
415            
416            this.entry  = entry;
417        }
418        
419        /**
420         * JSON Object Constructor
421         * @param jo A Json-Object having data about an instance of {@code 'entryAdded'}.
422         */
423        public entryAdded (JsonObject jo)
424        {
425            super("Log", "entryAdded", 1);
426        
427            this.entry  = ReadJSON.getObject(jo, "entry", Log.LogEntry.class, false, true);
428        }
429        
430        
431        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
432        public boolean equals(Object other)
433        {
434            if (this == other)                       return true;
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 = 31000000 + 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            (webSocketID, requestJSON, VOID_RETURN.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 = 31001000 + 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            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
516    }
517    
518    /**
519     * Enables log domain, sends the entries collected so far to the client by means of the
520     * {@code entryAdded} 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 = 31002000 + 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            (webSocketID, requestJSON, VOID_RETURN.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) THROWS.throwNPE("config");
572        
573        final int       webSocketID = 31003000 + 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            (webSocketID, requestJSON, VOID_RETURN.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 = 31004000 + 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            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
619    }
620    
621}