private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConnection,
            GuacamoleClientInformation info, Map<String, String> tokens,
            boolean interceptErrors) throws GuacamoleException {
        
        // Record new active connection
        Runnable cleanupTask = new ConnectionCleanupTask(activeConnection);
        try {
            // This MUST happen before getUUID() is invoked, to ensure the ID driving the UUID exists
            connectionRecordMapper.insert(activeConnection.getModel(),
                    environment.getCaseSensitivity());
            activeTunnels.put(activeConnection.getUUID().toString(), activeConnection);
        }

        // Execute cleanup if connection history could not be updated
        catch (RuntimeException | Error e) {
            cleanupTask.run();
            throw e;
        }

        try {

            GuacamoleConfiguration config;

            // Retrieve connection information associated with given connection record
            ModeledConnection connection = activeConnection.getConnection();

            // Pull configuration directly from the connection, additionally
            // joining the existing active connection (without sharing profile
            // restrictions) if such a connection exists
            if (activeConnection.isPrimaryConnection()) {
                activeConnections.put(connection.getIdentifier(), activeConnection);
                activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection);
                config = getGuacamoleConfiguration(connection, activeConnection.getConnectionID(), null);
            }

            // If we ARE joining an active connection under the restrictions of
            // a sharing profile, generate a configuration which does so
            else {

                // Verify that the connection ID is known
                String connectionID = activeConnection.getConnectionID();
                if (connectionID == null)
                    throw new GuacamoleResourceNotFoundException("No existing connection to be joined.");

                // Build configuration from the sharing profile and the ID of
                // the connection being joined
                config = getGuacamoleConfiguration(connection, connectionID, activeConnection.getSharingProfile());

            }
            
            // Make a copy of the tokens
            tokens = new HashMap<>(tokens);

            // Set up JDBC-specific tokens
            tokens.put(JDBC_DATE_TOKEN,
                    new SimpleDateFormat(JDBC_DATE_TOKEN_FORMAT)
                        .format(activeConnection.getStartDate()));
            tokens.put(JDBC_TIME_TOKEN,
                    new SimpleDateFormat(JDBC_TIME_TOKEN_FORMAT)
                        .format(activeConnection.getStartDate()));
            tokens.put(JDBC_CONNECTION_NAME_TOKEN, activeConnection.getConnectionName());
            tokens.put(JDBC_CONNECTION_ID_TOKEN, activeConnection.getConnectionIdentifier());
            tokens.put(JDBC_CONNECTION_HOSTNAME_TOKEN,
                    activeConnection.getConnection().getConfiguration().getParameter(JDBC_CONNECTION_HOSTNAME_TOKEN_PARAMETER));
            tokens.put(JDBC_CONNECTION_PROTOCOL_TOKEN,
                    activeConnection.getConnection().getConfiguration().getProtocol());
            
            // Include history record UUID as token
            tokens.put("HISTORY_UUID", activeConnection.getUUID().toString());

            // Build token filter containing credential tokens
            TokenFilter tokenFilter = new TokenFilter();
            tokenFilter.setTokens(tokens);

            // Filter the configuration
            tokenFilter.filterValues(config.getParameters());

            // Obtain socket which will automatically run the cleanup task
            ConfiguredGuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                getUnconfiguredGuacamoleSocket(connection.getGuacamoleProxyConfiguration(),
                        cleanupTask), config, info);

            // Assign and return new tunnel
            if (interceptErrors)
                return activeConnection.assignGuacamoleTunnel(new FailoverGuacamoleSocket(socket), socket.getConnectionID());
            else
                return activeConnection.assignGuacamoleTunnel(socket, socket.getConnectionID());
            
        }

        // Execute cleanup if socket could not be created
        catch (GuacamoleException e) {
            cleanupTask.run();
            throw e;
        }

    }
Creates a tunnel for the given user which connects to the given
connection, which MUST already be acquired via acquire(). The given
client information will be passed to guacd when the connection is
established.

The connection will be automatically released when it closes, or if it
fails to establish entirely.

@param activeConnection
    The active connection record of the connection in use.

@param info
    Information describing the Guacamole client connecting to the given
    connection.

@param tokens
    A Map containing the token names and corresponding values to be
    applied as parameter tokens when establishing the connection.

@param interceptErrors
    Whether errors from the upstream remote desktop should be
    intercepted and rethrown as GuacamoleUpstreamExceptions.

@return
    A new GuacamoleTunnel which is configured and connected to the given
    connection.

@throws GuacamoleException
    If an error occurs while the connection is being established, or
    while connection configuration information is being retrieved.
extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java