All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jitsi.xmpp.mucclient.MucClientConfiguration Maven / Gradle / Ivy

The newest version!
/*
 * Copyright @ 2018 - present, 8x8 Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.jitsi.xmpp.mucclient;

import org.jitsi.service.configuration.*;
import org.jitsi.utils.logging.*;
import org.jivesoftware.smack.*;

import java.util.*;

/**
 * Represents the configuration of a {@link MucClient}.
 *
 * @author Boris Grozev
 */
public class MucClientConfiguration
{
    /**
     * The {@link Logger} used by the {@link MucClientConfiguration} class and
     * its instances for logging output.
     */
    private static final Logger logger
        = Logger.getLogger(MucClientConfiguration.class);

    /**
     * The name of the property (without a prefix) which specifies the
     * hostname to connect to.
     * This is a required property.
     */
    public static String HOSTNAME = "HOSTNAME";

    /**
     * The name of the property (without a prefix) which specifies the
     * xmpp server's port to connect to.
     * This is an optional property and defaults to 5222.
     */
    public static String PORT = "PORT";

    /**
     * The name of the property (without a prefix) which specifies the
     * XMPP domain to use.
     * This is not a required property (if it is missing the hostname is
     * used as a domain)
     */
    public static String DOMAIN = "DOMAIN";

    /**
     * The name of the property (without a prefix) which specifies the
     * username to use to authenticate.
     * This is a required property.
     */
    public static String USERNAME = "USERNAME";

    /**
     * The name of the property (without a prefix) which specifies the
     * password to use to authenticate.
     * This is a required property.
     */
    public static String PASSWORD = "PASSWORD";

    /**
     * The name of the property (without a prefix) which specifies a
     * comma-separated list of full JIDs of the MUCs to join, e.g.:
     * {@code [email protected],[email protected]}
     *
     * This is a required property.
     */
    public static String MUC_JIDS = "MUC_JIDS";

    /**
     * The name of the property (without a prefix) which specifies the
     * nickname (i.e. the XMPP resource part) to use when joining the MUC.
     *
     * This is a required property.
     */
    public static String MUC_NICKNAME = "MUC_NICKNAME";

    /**
     * The name of the property (without a prefix) which specifies
     * whether to disable TLS certificate verifications.
     *
     * This is not a required property, the default behavior is to perform
     * verification.
     */
    public static String DISABLE_CERTIFICATE_VERIFICATION
        = "DISABLE_CERTIFICATE_VERIFICATION";

    /**
     * The name of the property (without a prefix) which specifies
     * the mode (sync or async) to use for the Smack IQ request handler.
     *
     * This is not a required property.
     */
    public static String IQ_HANDLER_MODE = "IQ_HANDLER_MODE";

    /**
     * The name of the property (without a prefix) which specifies
     * the security mode ("required", "ifpossible", or "disabled")
     * for the Smack XMPP connection.
     */
    public static String SECURITY_MODE = "SECURITY_MODE";

    /**
     * Loads a list of {@link MucClientConfiguration} objects based on
     * properties read from a {@link ConfigurationService} with a given
     * {@code prefix}.
     * See {@link #loadFromMap(Map, String, boolean)} for the format of the
     * properties.
     *
     * @param config the {@link ConfigurationService} to read properties from.
     * @param prefix the prefix for property names.
     * @param removeIncomplete whether to remove any incomplete (see
     * {@link MucClientConfiguration#isComplete()}) entries from the returned
     * collection, or to return all of them regardless.
     *
     * @return a list of {@link MucClientConfiguration}s described by properties
     * in {@code config} with a prefix of {@code prefix}.
     */
    public static Collection loadFromConfigService(
        ConfigurationService config, String prefix, boolean removeIncomplete)
    {
        Map properties = new HashMap<>();
        for (String pname : config.getPropertyNamesByPrefix(prefix, false))
        {
            properties.put(pname, config.getString(pname));
        }

        return loadFromMap(properties, prefix, removeIncomplete);
    }

    /**
     * Loads a list of {@link MucClientConfiguration} objects based on
     * properties in a {@link Map} with a given {@code prefix}.
     *
     * The properties can be described with map entries like this for an
     * ID of "":
     * PREFIX.HOSTNAME=hostname1
     * PREFIX.DOMAIN=domain
     *
     * Or like this for an ID of "id1":
     * PREFIX.id1.HOSTNAME=hostname2
     * PREFIX.id1.USERNAME=user
     *
     * @param properties the {@link Map} which contains the properties.
     * @param prefix the common prefix (to be ignored) for the keys in the map.
     * @param removeIncomplete whether to remove any incomplete (see
     * {@link MucClientConfiguration#isComplete()}) entries from the returned
     * collection, or to return all of them regardless.
     *
     * @return a list of {@link MucClientConfiguration}s described by the
     * entries of {@code properties} with a prefix of {@code prefix}.
     */
    public static Collection loadFromMap(
        Map properties, String prefix, boolean removeIncomplete)
    {
        Map configurations = new HashMap<>();

        for (String pname : properties.keySet())
        {
            String stripped = pname.substring(prefix.length());
            String id = "";
            String prop = stripped;
            if (stripped.contains("."))
            {
                id = stripped.substring(0, stripped.indexOf("."));
                prop = stripped.substring(id.length() + 1);
            }

            MucClientConfiguration c
                = configurations.computeIfAbsent(
                id,
                MucClientConfiguration::new);
            c.setProperty(prop, properties.get(pname));
        }

        if (removeIncomplete)
        {
            configurations.values().removeIf(
                c ->
                {
                    if (!c.isComplete())
                    {
                        logger.warn(
                            "Ignoring incomplete configuration with id=" + c
                                .getId());
                        return true;
                    }
                    return false;
                });
        }

        return configurations.values();
    }

    /**
     * Holds the properties of this {@link MucClientConfiguration}. To make
     * the property names case insensitive we always store the keys in upper
     * case.
     */
    private final HashMap props = new HashMap<>();

    /**
     * The ID of this {@link MucClientConfiguration}.
     */
    private final String id;

    /**
     * Initializes a new {@link MucClientConfiguration} instance.
     * @param id the ID.
     */
    public MucClientConfiguration(String id)
    {
        this.id = id;
    }

    /**
     * @return the ID of this {@link MucClientManager}.
     */
    public String getId()
    {
        return id;
    }

    /**
     * @return the hostname (i.e. the address to connect to).
     */
    public String getHostname()
    {
        return props.get(HOSTNAME.toUpperCase());
    }

    /**
     * Sets the hostname (i.e. the address to connect to).
     * @param hostname the hostname
     */
    public void setHostname(String hostname)
    {
        props.put(HOSTNAME, hostname);
    }

    /**
     * @return the XMPP server's port number.
     */
    public String getPort()
    {
        return props.get(PORT.toUpperCase());
    }

    /**
     * Sets the XMPP server's port.
     * @param port the XMPP server's port
     */
    public void setPort(String port)
    {
        props.put(PORT, port);
    }

    /**
     * @return the XMPP domain.
     */
    public String getDomain()
    {
        return props.get(DOMAIN.toUpperCase());
    }

    /**
     * Sets the XMPP domain.
     * @param domain the domain to set.
     */
    public void setDomain(String domain)
    {
        props.put(DOMAIN, domain);
    }

    /**
     * @return the username to use to authenticate to the XMPP server.
     */
    public String getUsername()
    {
        return props.get(USERNAME.toUpperCase());
    }

    /**
     * Sets the username to use to authenticate to the XMPP server.
     * @param username
     */
    public void setUsername(String username)
    {
        props.put(USERNAME, username);
    }

    /**
     * @return the password to use to authenticate to the XMPP server.
     */
    public String getPassword()
    {
        return props.get(PASSWORD.toUpperCase());
    }

    /**
     * Sets the password to use to authenticate to the XMPP server.
     * @param password
     */
    public void setPassword(String password)
    {
        props.put(PASSWORD, password);
    }

    /**
     * @return the JID of the MUC to join, e.g.
     * "[email protected],[email protected]"
     */
    public List getMucJids()
    {
        String str = props.get(MUC_JIDS.toUpperCase());
        if (str != null)
        {
            return Arrays.asList(str.split(","));
        }

        return null;
    }

    /**
     * Sets the list of JIDs of the MUCs to join.
     * @param mucJids the list of full JIDs of the MUCs to join.
     */
    public void setMucJids(List mucJids)
    {
        props.put(MUC_JIDS, String.join(",", mucJids));
    }

    /**
     * @return the nickname to use when joining the MUCs.
     */
    public String getMucNickname()
    {
        return props.get(MUC_NICKNAME.toUpperCase());
    }

    /**
     * Sets the nickname to use when joining the MUCs.
     * @param mucNickname the nickname.
     */
    public void setMucNickname(String mucNickname)
    {
        props.put(MUC_NICKNAME, mucNickname);
    }

    /**
     * @return whether TLS certificate verification should be disabled.
     */
    public boolean getDisableCertificateVerification()
    {
        return Boolean.parseBoolean(props.get(DISABLE_CERTIFICATE_VERIFICATION));
    }

    /**
     * Sets whether TLS certificate verification should be disabled.
     * @param disableCertificateVerification whether to disable TLS certificate
     * verification.
     */
    public void setDisableCertificateVerification(
        boolean disableCertificateVerification)
    {
        props.put(DISABLE_CERTIFICATE_VERIFICATION, Boolean.TRUE.toString());
    }

    /**
     * @return a string which represents the mode (sync or async) to use
     * for the smack IQ request handler.
     */
    public String getIqHandlerMode()
    {
        return props.get(IQ_HANDLER_MODE);
    }

    /**
     * Sets string which represents the mode (sync or async) to use
     * for the smack IQ request handler.
     */
    public void setIqHandlerMode(String iqHandlerMode)
    {
        props.put(IQ_HANDLER_MODE, iqHandlerMode);
    }

    /**
     * Gets the security mode for the Smack XMPP connection.
     * @throws IllegalArgumentException if it's not a valid security mode ("required", "ifpossible", "disabled",
     * or null).
     */
    public ConnectionConfiguration.SecurityMode getSecurityMode()
    {
        String securityModeStr = props.get(SECURITY_MODE);
        if (securityModeStr == null)
        {
            return null;
        }
        return ConnectionConfiguration.SecurityMode.valueOf(securityModeStr);
    }

    /**
     * Sets the security mode ("required", "ifpossible", or "disabled")
     * for the Smack XMPP connection, or null for the default behavior.
     */
    public void setSecurityMode(ConnectionConfiguration.SecurityMode securityMode)
    {
        props.put(SECURITY_MODE, securityMode != null ? securityMode.toString() : null);
    }

    /**
     * Checks whether this {@link MucClientConfiguration} has all of the required
     * properties.
     * @return {@code true} if all required properties are set, and
     * {@code false} otherwise.
     */
    public boolean isComplete()
    {
        /* Validate that security mode is valid. */
        try
        {
            getSecurityMode();
        }
        catch (IllegalArgumentException e)
        {
            return false;
        }
        return getHostname() != null && getUsername() != null
            && getPassword() != null
            && getMucJids() != null
            && getMucNickname() != null;
    }

    /**
     * Sets a property.
     * @param name the name of the property.
     * @param value the value to set.
     */
    public void setProperty(String name, String value)
    {
        props.put(name.toUpperCase(), value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        return
            "[ " + MucClientConfiguration.class.getName() +
                " id=" + id+
                " domain=" + getDomain() +
                " hostname=" + getHostname() +
                " port=" + getPort() +
                " username=" + getUsername() +
                " mucs=" + getMucJids() +
                " mucNickname=" + getMucNickname() +
                " disableCertificateVerification="
                    + getDisableCertificateVerification() +
                "]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy