Class Protocol

  • Direct Known Subclasses:
    FileProtocol, MemoryProtocol, PipeProtocol, TcpProtocol

    public abstract class Protocol
    extends Object
    This is the abstract base class for a protocol. A protocol is responsible for transporting packets.

    A protocol is responsible for the transport of packets. This base class offers all necessary methods to handle the protocol options, and it declares several abstract protocol specific methods for handling protocol destinations like connecting or writing packets.

    The following table lists the available protocols together with their identifier in the connections string and a short description.

    Available protocols
    Protocol Identifier Description
    FileProtocol "file" Used for writing log files in the standard SmartInspect binary log file format which can be loaded into the Console.
    MemoryProtocol "mem" Used for writing log data to memory and saving it to a stream on request.
    PipeProtocol "pipe" Used for sending log data over a named pipe directly to a local Console.
    TcpProtocol "tcp" Used for sending packets over a TCP connection directly to the Console.
    TextProtocol "text" Used for writing log files in a customizable text format. Best suited for end-user notification purposes.

    There are several options which are common to all protocols and beyond that each protocol has its own set of additional options. For those protocol specific options, please refer to the documentation of the corresponding protocol class. Protocol options can be set with Initialize and derived classes can query option values using the Get methods.

    The public members of this class are threadsafe.

    • Field Detail

      • fConnected

        protected boolean fConnected
    • Constructor Detail

      • Protocol

        public Protocol()
        Creates and initializes a Protocol subclass instance. For a list of protocol options common to all protocols, please refer to the isValidOption method.
    • Method Detail

      • handleException

        protected void handleException​(String message)
                                throws ProtocolException
        Handles a protocol exception.

        This method handles an occurred protocol exception. It first sets the Failed flag and creates a ProtocolException object with the name and options of this protocol. In normal blocking mode (see IsValidOption), it then throws this exception. When operating in asynchronous mode, it invokes the Error event handlers instead and does not throw an exception.

        Parameters:
        message - The exception message
        Throws:
        ProtocolException - Always in normal blocking mode, never in asynchronous mode
      • buildOptions

        protected void buildOptions​(ConnectionsBuilder builder)
        Fills a ConnectionsBuilder instance with the options currently used by this protocol.

        The filled options string consists of key, value option pairs separated by commas.

        This function takes care of the options common to all protocols. To include protocol specific options, override this function.

        Parameters:
        builder - The ConnectionsBuilder object to fill with the current options of this protocol
      • initialize

        public void initialize​(String options)
                        throws SmartInspectException
        Sets and initializes the options of this protocol.

        This method expects an options string which consists of key, value pairs separated by commas like this: "filename=log.sil, append=true". To use a comma in a value, you can use quotation marks like in the following example: "filename=\"log.sil\", append=true".

        Please note that a SmartInspectException exception is thrown if a wrong options string is assigned. A wrong options string could use an invalid syntax or contain one or more unknown option keys. This method can be called only once. Further calls have no effect. Pass null or an empty string to use the default options of a particular protocol.

        Parameters:
        options - The new protocol options
        Throws:
        SmartInspectException - If invalid options syntax, an unknown option key
      • getStringOption

        protected String getStringOption​(String key,
                                         String defaultValue)
        Gets the string of a key.
        Parameters:
        key - The key to search for
        defaultValue - The value to return if the key does not exist. Note that this method can throw an exception of type NullPointerException if you pass a null reference as key
        Returns:
        Either the value if the key exists or defaultValue otherwise
        Throws:
        NullPointerException - If the key argument is null
      • getIntegerOption

        protected int getIntegerOption​(String key,
                                       int defaultValue)
        Gets the integer value of a key.

        Please note that if a related value could be found but is not a valid integer, the supplied default value will be returned. Only non-negative integers will be recognized as valid values. Note that this method can throw an exception of type NullPointerException if you pass a null reference as key.

        Parameters:
        key - The key to search for
        defaultValue - The value to return if the key does not exist
        Returns:
        Either the value if the key exists and is a valid integer or defaultValue otherwise
        Throws:
        NullPointerException - If the key argument is null
      • getBooleanOption

        protected boolean getBooleanOption​(String key,
                                           boolean defaultValue)
        A Boolean value will be treated as true if the value of the key matches either "true", "yes" or "1" and as false otherwise. Note that this method can throw an exception of type NullPointerException if you pass a null reference as key.
        Parameters:
        key - The key to search for
        defaultValue - The value to return if the key does not exist
        Returns:
        Either the value if the key exists or defaultValue otherwise
        Throws:
        NullPointerException - If the key argument is null
      • getLevelOption

        protected Level getLevelOption​(String key,
                                       Level defaultValue)
        This method returns the defaultValue argument if either the supplied key is unknown or the found value is not a valid Level value. Please see the Level enum for more information on the available values. Note that this method can throw an exception of type NullPointerException if you pass a null reference as key.
        Parameters:
        key - The key whose value to return
        defaultValue - The value to return if the given key is unknown
        Returns:
        Either the value converted to the corresponding Level value for the given key if an element with the given key exists and the found value is a valid Level value or defaultValue otherwise
        Throws:
        NullPointerException - if the key argument is null
      • getSizeOption

        protected long getSizeOption​(String key,
                                     long defaultValue)
        Gets an integer value of a key. The integer value is interpreted as a byte size, and it is supported to specify byte units. This method returns the defaultValue argument if either the supplied key is unknown or the found value is not a valid integer or ends with an unknown byte unit. Only non-negative integer values are recognized as valid.

        It is possible to specify a size unit at the end of the value. If a known unit is found, this function multiplies the resulting value with the corresponding factor. For example, if the value of the element is "1KB", the return value of this function would be 1024.

        The following table lists the available units together with a short description and the corresponding factor:

        Size units
        Unit Name Description Factor
        KB Kilo Byte 1024
        MB Mega Byte (1024)^2
        GB Giga Byte (1024)^3

        If no unit is specified, this function defaults to the KB unit.

        Note: This method can throw a NullPointerException if you pass a null reference as key.

        Parameters:
        key - The key whose value to return
        defaultValue - The value to return if the given key is unknown
        Returns:
        Either the value converted to an integer for the given key if an element with the given key exists and the found value is a valid integer, or defaultValue otherwise.
        Throws:
        NullPointerException - if the key argument is null
      • getTimespanOption

        protected long getTimespanOption​(String key,
                                         long defaultValue)
        Gets an integer value of a key. The integer value is interpreted as a time span and it is supported to specify time span units.

        This method returns the defaultValue argument if either the supplied key is unknown or the found value is not a valid integer or ends with an unknown time span unit. It is possible to specify a time span unit at the end of the value. If a known unit is found, this function multiplies the resulting value with the corresponding factor. For example, if the value of the element is "1s", the return value of this function would be 1000. The following table lists the available units together with a short description and the corresponding factor.

        Time nits
        Unit Name Description Factor
        s Seconds 1000
        m Minutes 60*s
        h Hours 60*m
        d Days 24*h

        If no unit is specified, this function defaults to the Seconds unit. Please note that the value is always returned in milliseconds.

        Parameters:
        key - The key whose value to return
        defaultValue - The value to return if the given key is unknown
        Returns:
        Either the value converted to an integer for the given key if an element with the given key exists and the found value is a valid integer or defaultValue otherwise. The value is returned in milliseconds
        Throws:
        NullPointerException - if The key argument is null
      • getRotateOption

        protected FileRotate getRotateOption​(String key,
                                             FileRotate defaultValue)
        Gets a FileRotate value of a key.
        Parameters:
        key - The key whose value to return
        defaultValue - The value to return if the given key is unknown
        Returns:
        Either the value converted to a FileRotate value for the given key if an element with the given key exists and the found value is a valid FileRotate or defaultValue otherwise. Note that this method can throw a NullPointerException if you pass a null reference as key
        Throws:
        NullPointerException - if the key argument is null
      • getBytesOption

        public byte[] getBytesOption​(String key,
                                     int size,
                                     byte[] defaultValue)
        Gets the byte array value of a key.

        The returned byte array always has the desired length as specified by the size argument. If the element value does not have the required size after conversion, it is shortened or padded (with zeros) automatically. This method returns the defaultValue argument if either the supplied key is unknown or the found value does not have a valid format (e.g. invalid characters when using hexadecimal strings).

        Note that this method can throw an exception of type NullPointerException if you pass a null reference as key.

        Parameters:
        key - The key whose value to return
        size - The desired size in bytes of the returned byte array. If the element value does not have the expected size, it is shortened or padded automatically
        defaultValue - The value to return if the given key is unknown or if the found value has an invalid format
        Returns:
        Either the value converted to a byte array for the given key if an element with the given key exists and the found value has a valid format or defaultValue otherwise
        Throws:
        NullPointerException - if the key argument is null
      • isValidOption

        protected boolean isValidOption​(String name)
        Validates if an option is supported by this protocol.

        The following table lists all valid options, their default values and descriptions common to all protocols. See below for explanations:

        Protocol options
        Option Name Default Description
        - - -
        level debug Specifies the log level of this protocol.
        reconnect false Specifies if a reconnect should be initiated when a connection gets dropped.
        reconnect.interval 0 If reconnecting is enabled, specifies the minimum time in seconds between two successive reconnect attempts. If 0 is specified, a reconnect attempt is initiated for each packet if needed. It is possible to specify time span units like this: "1s". Supported units are "s" (seconds), "m" (minutes), "h" (hours) and "d" (days).
        caption [name] Specifies the caption of this protocol as used by SmartInspect.Dispatch. By default, it is set to the protocol identifier (e.g., "file" or "mem").
        async.enabled false Specifies if this protocol should operate in asynchronous instead of the default blocking mode.
        async.queue 2048 Specifies the maximum size of the asynchronous queue in kilobytes. It is possible to specify size units like this: "1 MB". Supported units are "KB", "MB" and "GB".
        async.throttle true Specifies if the application should be automatically throttled in asynchronous mode when more data is logged than the queue can handle.
        async.clearondisconnect false Specifies if the current content of the asynchronous queue should be discarded before disconnecting. Useful if an application must not wait for the logging to complete before exiting.
        backlog.enabled false Enables the backlog feature (see below).
        backlog.queue 2048 Specifies the maximum size of the backlog queue in kilobytes. It is possible to specify size units like this: "1 MB". Supported units are "KB", "MB" and "GB".
        backlog.flushon error Specifies the flush level for the backlog functionality.
        backlog.keepopen false Specifies if the connection should be kept open between two successive writes when the backlog feature is used.

        With the log level of a protocol you can limit the amount of data being logged by excluding packets which don't have a certain minimum log level. For example, if you set the level to "message", all packets with a log level of "debug" or "verbose" are ignored. For a complete list of available log level values, please see the documentation of the Level enum.

        The caption option specifies the caption for this protocol as used by the SmartInspect.Dispatch method. This method can send and initiate custom protocol actions and the caption is used to lookup the requested connection. By default, the caption is set to the identifier of a protocol (e.g., "file" or "mem"). For more information about the dispatching of custom protocol actions, please refer to the documentation of the Dispatch and SmartInspect.Dispatch methods.

        If the backlog option is enabled, all packets whose log level is less than the flushon level and equal to or higher than the general log level of a protocol, will be written to a queue rather than directly to the protocol specific destination. When a packet arrives with a log level of at least the same value as the flushon option, the current content of the queue is written. The total amount of memory occupied by this queue can be set with the queue option. If the packet queue has been filled up with packets and a new packet is about to be stored, old packets are discarded.

        As an example, if the backlog queue is set to "2 MB" and the flushon level to "error", all packets with a log level less than error are written to a queue first. By specifying a queue option of "2 MB", the baclog queue is set to a maximum memory size of 2 megabyte. Now, when a packet with a log level of error arrives, the current content of the queue and then the error itself is written.

        With the keepopen option of the backlog feature you can specify if a connection should be kept open between two successive writes. When keepopen is set to false, a connection is only available during the actual write / flush. A connection is thus only created when absolutely necessary.

        A protocol can either operate in normal blocking (the default) or in asynchronous mode. In blocking mode, the operations of this protocol (Connect, Disconnect, Dispatch and WritePacket) are executed synchronously and block the caller until they are done. In asynchronous mode, these operations are not executed directly but scheduled for execution in a different thread and return immediately. Asynchronous logging can increase the logging performance and reduce the blocking of applications.

        When operating in asynchronous mode, this protocol uses a queue to buffer the logging data. The total amount of memory occupied by this queue can be set with the queue option. The throttle option specifies if an application should be automatically throttled in asynchronous mode when more data is logged / generated than the queue can handle. If this option is disabled and the queue is currently full, old packets are discarded when new data is logged. The throttle option ensures that no logging data is lost but can be disabled if logging performance is critical.

        With the clearondisconnect option, you can specify if the current content of the asynchronous queue should be discarded before disconnecting. This can be useful if an application must not wait for the logging to complete before exiting.

        The reconnect option allows a protocol to reconnect automatically before a packet is being written. A reconnect might be necessary if a working connection has been unexpectedly disconnected or could not be established in the first place. Possible errors during a reconnect attempt will silently be ignored and not reported.

        Please note that the reconnect functionality causes a protocol by default to initiate a connection attempt for every packet until a connection has been successfully (re-) established. This can be a very time-consuming process, especially when using a protocol which requires a complex connection process like TCP, for example. This can slow down the logging performance. When using the reconnect option, it is thus recommended to also enable asynchronous logging to not block the application or to specify a reconnect interval to minimize the reconnect attempts.

        Parameters:
        name - The option name to validate
        Returns:
        True if the option is supported and false otherwise
      • loadOptions

        protected void loadOptions()
        Loads and inspects protocol specific options.

        This method is intended to give real protocol implementations the opportunity to load and inspect options. This method will be called automatically when the options have been changed. The default implementation of this method takes care of the options isValidOption(java.lang.String) common to all protocols and should thus always be called by derived classes which override this method.

      • getReconnectDefaultValue

        protected boolean getReconnectDefaultValue()
        Defines the default value for `reconnect` option as `true`.
        Returns:
        false
      • getAsyncEnabledDefaultValue

        protected boolean getAsyncEnabledDefaultValue()
        Defines the default value for `async.enabled` option as `false`.
        Returns:
        false
      • getAsyncThrottleDefaultValue

        protected boolean getAsyncThrottleDefaultValue()
        Defines the default value for `async.throttle` option as `false`.
        Returns:
        true
      • getAsyncQueueDefaultValue

        protected int getAsyncQueueDefaultValue()
        Defines the default value for `async.queue` option as 2 megabytes.
        Returns:
        2048 KB
      • reset

        protected void reset()
                      throws Exception
        Resets the protocol and brings it into a consistent state.

        This method resets the current protocol state by clearing the internal queue of packets, setting the connected status to false and calling the abstract internalDisconnect method of a real protocol implementation to clean up any protocol specific resources.

        Throws:
        Exception - exception
      • internalConnect

        protected abstract void internalConnect()
                                         throws Exception
        Connects to the protocol destination.

        This method initiates a protocol specific connection attempt. The behavior of real implementations of this method can often be changed by setting protocol options with the initialize method. This method is always called in a threadsafe and exception-safe context.

        Throws:
        Exception - If connecting to the destination failed.
      • connect

        public void connect()
                     throws ProtocolException
        Connects to the protocol destination.

        In normal blocking mode (see isValidOption), this method does nothing more than to verify that the protocol is not already connected and does not use the keep-open backlog feature, and then calls the abstract protocol specific internalConnect method in a threadsafe and exception-safe context.
        When operating in asynchronous mode instead, this method schedules a connect operation for asynchronous execution and returns immediately. Please note that possible exceptions which occur during the eventually executed connect are not thrown directly but reported with the error event.

        Throws:
        ProtocolException - If connecting to the destination fails. Can only occur when operating in normal blocking mode. In asynchronous mode, the error event is used for reporting exceptions instead
      • internalReconnect

        protected boolean internalReconnect()
                                     throws Exception
        Reconnects to the protocol specific destination.

        This method initiates a protocol specific reconnect attempt. The behavior of real method implementations can often be changed by setting protocol options with initialize. This method is always called in a threadsafe and exception-safe context.

        The default implementation simply calls the protocol specific internalConnect method. Derived classes can change this behavior by overriding this method.

        Returns:
        True if the reconnect attempt has been successful and false otherwise
        Throws:
        Exception - if reconnecting to the destination failed
      • internalDisconnect

        protected abstract void internalDisconnect()
                                            throws Exception
        Disconnects from the protocol destination.

        This method is intended for real protocol implementations to disconnect from the protocol specific source. This could be closing a file or disconnecting a TCP socket, for example. This method is always called in a threadsafe and exception-safe context.

        Throws:
        Exception - If disconnecting from the destination failed
      • disconnect

        public void disconnect()
                        throws ProtocolException
        Disconnects from the protocol destination.

        In normal blocking mode (see isValidOption), this method checks if this protocol has a working connection and then calls the protocol specific internalDisconnect method in a threadsafe and exception-safe context.

        When operating in asynchronous mode instead, this method schedules a disconnect operation for asynchronous execution and then blocks until the internal protocol thread is done. Please note that possible exceptions which occur during the eventually executed disconnect are not thrown directly but reported with the ProtocolListener.onError, error event.

        Throws:
        ProtocolException - Disconnecting from the destination failed. Can only occur when operating in normal blocking mode. In asynchronous mode, the error event is used for reporting exceptions instead
      • composeLogHeaderPacket

        protected LogHeader composeLogHeaderPacket()
      • internalWriteLogHeader

        protected void internalWriteLogHeader()
                                       throws Exception
        Throws:
        Exception
      • internalWritePacket

        protected abstract void internalWritePacket​(Packet packet)
                                             throws Exception
        Writes a packet to the protocol destination.

        This method is intended for real protocol implementations to write the supplied packet to the protocol specific destination. This method is always called in a threadsafe and exception-safe context.

        Parameters:
        packet - The packet to write
        Throws:
        Exception - if writing the packet to the destination failed
      • writePacket

        public void writePacket​(Packet packet)
                         throws ProtocolException
        Writes a packet to the protocol specific destination.

        This method first checks if the log level of the supplied packet is sufficient to be logged. If this is not the case, this method returns immediately.

        Otherwise, in normal blocking mode (see isValidOption(java.lang.String)), this method verifies that this protocol is successfully connected and then writes the supplied packet to the backlog queue or passes it directly to the protocol specific destination by calling the InternalWritePacket method. Calling InternalWritePacket is always done in a threadsafe and exception-safe way.

        When operating in asynchronous mode instead, this method schedules a write operation for asynchronous execution and returns immediately. Please note that possible exceptions which occur during the eventually executed write are not thrown directly but reported with the error event.

        Parameters:
        packet - The packet to write
        Throws:
        ProtocolException - Writing the packet to the destination failed. Can only occur when operating in normal blocking mode. In asynchronous mode, the error event is used for reporting exceptions instead
      • getName

        protected abstract String getName()
        Specifies the name of a real protocol implementation.

        Real implementations should return a meaningful name which represents the protocol. For example, the FileProtocol returns "file", the TcpProtocol "tcp" and the TextProtocol "text".

        Returns:
        The name of a real protocol implementation
      • internalDispatch

        protected void internalDispatch​(ProtocolCommand command)
                                 throws Exception
        Executes a protocol specific custom action. The default implementation does nothing. Derived protocol implementations can override this method to add custom actions. Please see the MemoryProtocol.internalDispatch method for an example. This method is always called in a threadsafe and exception-safe way.
        Parameters:
        command - The protocol command which provides protocol specific information about the custom action.
        Throws:
        Exception - if executing the custom action failed.
        See Also:
        SmartInspect.dispatch(java.lang.String, int, java.lang.Object)
      • dispatch

        public void dispatch​(ProtocolCommand command)
                      throws ProtocolException
        Dispatches a custom action to a concrete implementation of a protocol.

        In normal blocking mode (see isValidOption), this method does nothing more than to call the protocol-specific internalDispatch method with the supplied command argument in a threadsafe and exception-safe way. Please note that this method dispatches the custom action only if the protocol is currently connected.

        When operating in asynchronous mode instead, this method schedules a dispatch operation for asynchronous execution and returns immediately. Please note that possible exceptions which occur during the eventually executed dispatch are not thrown directly but reported with the error event.

        Parameters:
        command - The protocol command object which provides protocol-specific information about the custom action. Can be null
        Throws:
        ProtocolException - An exception occurred in the custom action. Can only occur when operating in normal blocking mode. In asynchronous mode, the error event is used for reporting exceptions instead
        See Also:
        SmartInspect.dispatch(java.lang.String, int, java.lang.Object)
      • getCaption

        public String getCaption()
        Returns the caption of this protocol.

        The caption is used in the SmartInspect.dispatch method to lookup the requested connection. The caption can be set with initialize. If you use only one connection at once or does not use the SmartInspect.dispatch method, the caption option can safely be ignored. For more information, please refer to the documentation of the dispatch and SmartInspect.dispatch methods.

        Returns:
        The caption of this protocol as used by the SmartInspect.dispatch method
        See Also:
        SmartInspect.dispatch(java.lang.String, int, java.lang.Object)
      • dispose

        public void dispose()
                     throws ProtocolException
        Disconnects from the protocol destination.

        In normal blocking mode (see isValidOption), this method checks if this protocol has a working connection and then calls the protocol specific internalDisconnect method in a threadsafe and exception-safe context.

        When operating in asynchronous mode instead, this method schedules a disconnect operation for asynchronous execution and then blocks until the internal protocol thread is done. Please note that possible exceptions which occur during the eventually executed disconnect are not thrown directly but reported with the ProtocolListener.onError, error event.

        Throws:
        ProtocolException - Disconnecting from the destination failed. Can only occur when operating in normal blocking mode. In asynchronous mode, the error event is used for reporting exceptions instead
      • failed

        public boolean failed()
        Returns if the last executed connection-related operation of this protocol has failed. Indicates if the next operation is likely to block.
        Returns:
        True if the last executed connection-related operation of this protocol has failed and false otherwise
      • addListener

        public void addListener​(ProtocolListener listener)
        Adds a new listener for the events of this object. This method adds a new listener for the events of this Protocol object. This can be useful to get informed about possible protocol errors. Please see the ProtocolListener interface for details. Also see the documentation of the ProtocolAdapter class which simplifies the event handling. Note that the error event is only used in combination with asynchronous logging (please see isValidOption for more information). In normal blocking mode, exceptions are reported by throwing.
        Parameters:
        listener - The listener to add
      • removeListener

        public void removeListener​(ProtocolListener listener)
        Removes a new listener for the events of this object.

        This method removes the supplied listener from the event system of this object. After the listener has been removed, it will no longer be notified about any events of this object. Note that the error event is only used in combination with asynchronous logging (please see isValidOption for more information). In normal blocking mode, exceptions are reported by throwing.

        Parameters:
        listener - The listener to add
      • doError

        protected void doError​(Exception ex)
        Invokes the ProtocolListener.onError event handlers. Derived classes can override this method to intercept the ProtocolListener.onError event. Note that the error event is only used in combination with asynchronous logging (please see isValidOption for more information). In normal blocking mode, exceptions are reported by throwing.
        Parameters:
        ex - The occurred exception
      • isAsynchronous

        public boolean isAsynchronous()
        Indicates if this protocol is operating in asynchronous protocol mode. If this method returns true, this protocol is operating in asynchronous protocol mode. Otherwise, it returns false. Asynchronous protocol mode can be enabled with the initialize method. Also see isValidOption for information on asynchronous logging and how to enable it.
        Returns:
        True if this protocol is operating in asynchronous protocol mode and false otherwise
      • getHostName

        public String getHostName()
        Returns the hostname of this protocol.

        The hostname of a protocol is usually set to the name of the machine this protocol is created in. The hostname can be used to write LogHeader packets after a successful protocol connect.

        Returns:
        The hostname of this protocol
      • setHostName

        public void setHostName​(String hostName)
        Sets the hostname of this protocol.

        The hostname of a protocol is usually set to the name of the machine this protocol is created in. The hostname can be used to write LogHeader packets after a successful protocol connect.

        Parameters:
        hostName - The new hostname
      • getAppName

        public String getAppName()
        Returns the application name of this protocol.

        The application name of a protocol is usually set to the name of the application this protocol is created in. The application name can be used to write LogHeader packets after a successful protocol connect.

        Returns:
        The application name of this protocol
      • setAppName

        public void setAppName​(String appName)
        Sets the application name of this protocol.

        The application name of a protocol is usually set to the name of the application this protocol is created in. The application name can be used to write LogHeader packets after a successful protocol connect.

        Parameters:
        appName - The new application name