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

org.jdiameter.common.impl.validation.DictionaryImpl Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2016, TeleStax Inc. and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see 
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *   JBoss, Home of Professional Open Source
 *   Copyright 2007-2011, Red Hat, Inc. and individual contributors
 *   by the @authors tag. See the copyright.txt in the distribution for a
 *   full listing of individual contributors.
 *
 *   This is free software; you can redistribute it and/or modify it
 *   under the terms of the GNU Lesser General Public License as
 *   published by the Free Software Foundation; either version 2.1 of
 *   the License, or (at your option) any later version.
 *
 *   This software is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this software; if not, write to the Free
 *   Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 *   02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jdiameter.common.impl.validation;

import org.jdiameter.api.Message;
import org.jdiameter.api.validation.Dictionary;
import org.jdiameter.api.validation.*;
import org.jdiameter.client.impl.DictionarySingleton;
import org.jdiameter.client.impl.VersionProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.*;

/**
 * Implementation of {@link Dictionary} interface.
 *
 * @author  Bartosz Baranowski 
 * @author  Alexandre Mendonca 
 * @since 1.5.4.0-build404
 */
@SuppressWarnings("all") //3rd party lib
public class DictionaryImpl implements Dictionary
{

    private static transient Logger logger = LoggerFactory.getLogger(DictionaryImpl.class);

    public static Dictionary INSTANCE = getInstance("dictionary.xml");

    private static final String UNDEFINED_AVP_TYPE = "UNDEFINED";

    private static final String AVP_DEFAULT_INDEX = "-1";
    private static final String AVP_DEFAULT_MULTIPLICITY = AvpRepresentation._MP_ZERO_OR_MORE;

    public static final String _AVP_ATTRIBUTE_NAME = "name";
    public static final String _AVP_ATTRIBUTE_CODE = "code";
    public static final String _AVP_ATTRIBUTE_VENDOR = "vendor";
    public static final String _AVP_ATTRIBUTE_MULTIPLICITY = "multiplicity";
    public static final String _AVP_ATTRIBUTE_INDEX = "index";

    private Map avpMap = new HashMap();
    private Map avpByNameMap = new HashMap();

    private Map vendorMap = new HashMap();

    private Map commandMap = new HashMap();

    private Map typedefMap = new HashMap();

    private boolean configured = false;

    private DictionaryImpl(InputStream is)
    {
        init(is);
    }

    public static Dictionary getInstance(InputStream is)
    {
        if (is == null) {
            if (INSTANCE != null) {
                return INSTANCE;
            }
            // Maintaining 1.7.0 behaviour
            String confFile = "dictionary.xml";
            is = getInputStream(confFile);
        }
        if (INSTANCE != null) {
            ((DictionaryImpl) INSTANCE).init(is);
        } else {
            INSTANCE = new DictionaryImpl(is);
        }
        return INSTANCE;
    }

    public static Dictionary getInstance(String confFile)
    {
        if (confFile == null) {
            if (INSTANCE != null) {
                return INSTANCE;
            }
            confFile = "dictionary.xml";
        }
        InputStream is = getInputStream(confFile);
        return getInstance((InputStream) is);
    }

    private static InputStream getInputStream(String confFile)
    {
        InputStream is = null;

        try {
            is = DictionarySingleton.class.getResourceAsStream(confFile);
            if (is == null) {
                logger.debug(
                        "Dictionary configuration file: {}, not found in class classloader. Trying thread context class loader.",
                        confFile);
                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(confFile);
            }

            if (is == null) {
                logger.debug(
                        "Dictionary configuration file: {}, not found in thread context class loader. Trying using 'config/' prefix.",
                        confFile);
                is = Thread.currentThread().getContextClassLoader().getResourceAsStream("config/" + confFile);
            }

            if (is == null) {
                logger.debug(
                        "Fictionary configuration file: {}, not found in thread context class loader. Trying regular file.",
                        confFile);
                File fDict = new File(confFile);
                if (fDict.exists()) {
                    is = new FileInputStream(fDict);
                } else {
                    logger.debug(
                            "Dictionary configuration file: {}, not found from regular file. Trying using 'config/' prefix.",
                            confFile);
                    fDict = new File("config/" + confFile);
                    if (fDict.exists()) {
                        is = new FileInputStream(fDict);
                    }
                }
            }
        }
        catch (FileNotFoundException fnfe) {
            logger.warn("Could not load configuration file: {}, from any known location.", confFile);
        }
        return is;
    }

    private void init(InputStream is)
    {

        try {
            if (is != null) {
                this.configure(is);
            } else {
                this.setEnabled(false);
                logger.warn(
                        "Failed to initialize and configure Diameter Dictionary since configuration file was not found. Validator is disabled.");
            }
        }
        finally {
            if (is != null) {
                try {
                    is.close();
                }
                catch (IOException e) {
                    logger.error("", e);
                }
            }
        }
    }

    // Parser functions ---------------------------------------------------------

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#configure(java.io.InputStream)
     */
    @Override
    public void configure(InputStream is)
    {
        if (is == null) {
            logger.error("No input stream to configure dictionary from?");
            return;
        }
        try {
            long startTime = System.currentTimeMillis();
            this.avpByNameMap = new TreeMap(new Comparator()
            {
                @Override
                public int compare(String o1, String o2)
                {
                    return (o1 == null) ? 1 : (o2 == null) ? -1 : o1.compareTo(o2);
                }
            });

            this.vendorMap  = new HashMap();
            this.typedefMap = new HashMap();
            this.avpMap     = new HashMap();
            this.commandMap = new HashMap();

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(is);

            doc.getDocumentElement().normalize();

            this.parseVendors(doc);
            this.parseTypeDefs(doc);
            this.parseAvps(doc);
            this.parseCommands(doc);

            this.configured = true;

            long endTime = System.currentTimeMillis();

            if (logger.isInfoEnabled()) {
                logger.info("{} Diameter Dictionary loaded in {}ms -- Vendors[{}] Commands[{}] Types[{}] AVPs[{}]",
                            new Object[]{VersionProperties.instance.getProperty("vendor"), (endTime - startTime),
                                         vendorMap.size(), commandMap.size(), typedefMap.size(), avpMap.size()});
            }

            if (logger.isInfoEnabled()) {
                StringBuffer sb = new StringBuffer();
                int c = 0;
                for (AvpRepresentation key : this.avpMap.keySet()) {
                    if (this.avpMap.get(key).isWeak()) {
                        c++;
                        sb.append("---------------------------------\n").append("Found incomplete AVP definition:\n")
                          .append(this.avpMap.get(key)).append("\n");
                    }
                }

                if (c > 0) {
                    sb.append("------- TOTAL INCOMPLETE AVPS COUNT: ").append(c).append(" -------");
                    logger.info(sb.toString());
                }
            }
        }
        catch (Exception e) {
            this.enabled    = false;
            this.configured = false;
            logger.error("Failed to parse validator configuration. Validator disabled.", e);
        }
        finally {
            // close?
            try {
                is.close();
            }
            catch (IOException e) {
                logger.debug("Failed to close InputStream for Dictionary XML.", e);
            }
        }
    }

    /**
     * Parses the  attributes from a Dictionary XML Document
     *
     * @param doc the DOM object representing the XML Document with the Dictionary definitions
     */
    protected void parseVendors(Document doc)
    {
        // Parse vendors, we will need those.
        // Format: 
        NodeList vendorNodes = doc.getElementsByTagName("vendor");

        for (int v = 0; v < vendorNodes.getLength(); v++) {
            Node vendorNode = vendorNodes.item(v);
            if (vendorNode.getNodeType() == Node.ELEMENT_NODE) {
                Element vendorElement = (Element) vendorNode;

                // Get the Code (number) and ID (string)
                String vendorCode = vendorElement.getAttribute("code");
                String vendorId = vendorElement.getAttribute("vendor-id");

                vendorMap.put(vendorId, vendorCode);
            }
        }
    }

    /**
     * Parses the  attributes from a Dictionary XML Document
     *
     * @param doc the DOM object representing the XML Document with the Dictionary definitions
     */
    protected void parseTypeDefs(Document doc)
    {
        // Parse type definitions. Handy to match against defined AVP types
        // and to fill AVPs with generic function.
        // Format: 
        //         
        NodeList typedefNodes = doc.getElementsByTagName("typedefn");

        for (int td = 0; td < typedefNodes.getLength(); td++) {
            Node typedefNode = typedefNodes.item(td);
            if (typedefNode.getNodeType() == Node.ELEMENT_NODE) {
                Element typedefElement = (Element) typedefNode;

                String typeName = typedefElement.getAttribute("type-name");
                String typeParent = typedefElement.getAttribute("type-parent");

                // UTF8String and Time are special situations, we don't want to convert these.
                if (typeParent == null || typeParent.equals("") || typeName.equals("UTF8String") || typeName.equals("Time")) {
                    typeParent = typeName;
                }

                typedefMap.put(typeName, typeParent);
            }
        }
    }

    public void addAvpDef(String avpName, String avpDesc, long vendorId, int avpCode, boolean avpMayEncrypt, String avpMandatory,
                          String avpProtected, String avpVendorBit, String originalType, String avpType,
                          List groupedAvpChilds)
    {
        try {
            AvpRepresentationImpl avp = null;

            avp = new AvpRepresentationImpl(avpName, avpDesc, Integer.valueOf(avpCode), avpMayEncrypt,
                                            avpMandatory, avpProtected, avpVendorBit, vendorId, originalType, avpType);

            if (avp.isGrouped()) {
                avp.setChildren(groupedAvpChilds);

                // we are not strong enough, children are referenced ONLY by name, so we are
                // weak until all children can be resolved to strong representation
                avp.markWeak(true);
            }

            resolveWeakLinks(avp);

            AvpRepresentation existingAvp = null;
            if ((existingAvp = avpMap.get(avp)) != null) {
                logger.warn("Duplicated AVP Definition for AVP Code: {}, Vendor-Id: {}. See TRACE logs for definitions.",
                            avp.getCode(), avp.getVendorId());
                logger.trace("Existing AVP:\r\n {}\r\n New AVP:\r\n {}", existingAvp, avp);
            } else {
                avpMap.put(avp, avp);
            }

            AvpRepresentation oldAvp = avpByNameMap.put(avp.getName(), avp);

            if (oldAvp != null) {
                logger.debug("[WARN] Overwrited definition of AVP with the same name: Old: {}, New: {}",
                             new Object[]{oldAvp, avp});
            }
        }
        catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug(new StringBuffer("[ERROR] Failed adding AVP: Name[").append(avpName).append("] Description[")
                                                                                 .append("N/A").append("] Code[").append(avpCode).append("] May-Encrypt[").append(avpMayEncrypt)
                                                                                 .append("] Mandatory[").append(avpMandatory).append("] Protected [").append(avpProtected)
                                                                                 .append("] Vendor-Bit [").append(avpVendorBit).append("] Vendor-Id [").append(vendorId)
                                                                                 .append("] Constrained[").append("N/A").append("] OriginalType [").append(originalType)
                                                                                 .append("] Type [").append(avpType).append("]").toString(), e);
            }
        }
    }

    /**
     * Parses the  attributes from a Dictionary XML Document
     *
     * @param doc the DOM object representing the XML Document with the Dictionary definitions
     */
    protected void parseAvps(Document doc)
    {
        // Format:  
        //            
        //          

        NodeList avpDefnNodes = doc.getElementsByTagName("avpdefn");

        for (int i = 0; i < avpDefnNodes.getLength(); i++) {
            Node avpNode = avpDefnNodes.item(i);
            Element avpDefnElement = (Element) avpNode;

            String avpName = avpDefnElement.getAttribute("name");
            String avpCode = avpDefnElement.getAttribute("code");
            String avpVendorId = avpDefnElement.getAttribute("vendor-id");

            String avpMandatory = avpDefnElement.getAttribute("mandatory");
            String avpProtected = avpDefnElement.getAttribute("protected").equals("") ? "may"
                                                                                      : avpDefnElement.getAttribute("protected");
            String avpMayEncrypt = avpDefnElement.getAttribute("may-encrypt");
            String avpVendorBit = avpDefnElement.getAttribute("vendor-bit");

            long vendorCode = getVendorCode(avpVendorId);

            // Let's figure out the type
            // It can be:
            // 
            //  OR
            //   ... 
            //  OR
            //   ... 
            String avpOriginalType = UNDEFINED_AVP_TYPE;
            String avpType = avpOriginalType;
            List groupedAvpChilds = new ArrayList();

            NodeList avpDefnChildNodes = avpNode.getChildNodes();
            for (int j = 0; j < avpDefnChildNodes.getLength(); j++) {
                Node avpDefnChildNode = avpDefnChildNodes.item(j);

                if (avpDefnChildNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element avpDefnChildElement = (Element) avpDefnChildNode;

                    if (avpDefnChildElement.getNodeName().equals("grouped")) {
                        avpOriginalType = "Grouped";
                        avpType         = avpOriginalType;

                        // Let's fetch the childs
                        // Format: 
                        NodeList groupedAvpMembers = avpDefnChildElement.getChildNodes();

                        for (int gChildIndex = 0; gChildIndex < groupedAvpMembers.getLength(); gChildIndex++) {
                            Node groupedAvpChildNode = groupedAvpMembers.item(gChildIndex);

                            if (groupedAvpChildNode.getNodeType() == Node.ELEMENT_NODE) {
                                Element groupedAvpChildElement = (Element) groupedAvpChildNode;

                                String childName = null;
                                String childMultiplicity = AVP_DEFAULT_MULTIPLICITY;
                                String childIndexIndicator = AVP_DEFAULT_INDEX;

                                if (!groupedAvpChildElement.hasAttribute("name")) {
                                    if (logger.isDebugEnabled()) {
                                        logger.debug(new StringBuffer(
                                                "[ERROR] Grouped child does not have name, grouped avp:  Name[").append(avpName)
                                                                                                                .append("] Description[")
                                                                                                                .append("").append("] Code[").append(avpCode).append("] May-Encrypt[")
                                                                                                                .append(avpMayEncrypt).append("] Mandatory[")
                                                                                                                .append(avpMandatory).append("] Protected [").append(avpProtected)
                                                                                                                .append("] Vendor-Bit [").append(avpVendorBit).append("] Vendor-Id [")
                                                                                                                .append(avpVendorId).append("] Constrained[").append("").append("] Type [")
                                                                                                                .append(avpType).append("]").toString());
                                    }
                                    continue;
                                } else {
                                    childName = groupedAvpChildElement.getAttribute("name");
                                }

                                childMultiplicity = groupedAvpChildElement.hasAttribute("multiplicity")
                                                    ? groupedAvpChildElement.getAttribute("multiplicity")
                                                    : AvpRepresentation._MP_ZERO_OR_MORE;

                                childIndexIndicator = groupedAvpChildElement.hasAttribute("index")
                                                      ? groupedAvpChildElement.getAttribute("index")
                                                      : "-1";

                                // have we parsed this child definition already?
                                AvpRepresentation childRep = this.avpByNameMap.get(childName);
                                AvpRepresentationImpl child = null;
                                if (childRep != null) {
                                    try {
                                        child = (AvpRepresentationImpl) childRep.clone();
                                    }
                                    catch (CloneNotSupportedException cnse) {
                                        // It should not happen, but anyway
                                        if (logger.isWarnEnabled()) {
                                            logger.warn("Unable to clone AVP " + childRep, cnse);
                                        }
                                    }
                                } else {
                                    child = new AvpRepresentationImpl(childName, vendorCode);
                                    child.markWeak(true);
                                }
                                child.setMultiplicityIndicator(childMultiplicity);
                                child.markFixPosition(Integer.valueOf(childIndexIndicator));

                                groupedAvpChilds.add(child);
                            }
                        }
                    } else if (avpDefnChildElement.getNodeName().equals("type")) {
                        avpOriginalType = avpDefnChildElement.getAttribute("type-name");
                        avpType         = avpOriginalType;
                        //FIXME: baranowb: why this is like that? This changes type of AVP to primitive ONE..? Checks against type dont make sense, ie to check for Address type...
                        avpType = typedefMap.get(avpType);

                        if (avpType == null) {
                            logger.warn("Unknown AVP Type ({}) for AVP with code {} and vendor-id {} ",
                                        new Object[]{avpDefnChildElement.getAttribute("type-name"), avpCode,
                                                     avpVendorId});
                        }
                    } else {
                        logger.warn("Unknown AVP Definition child element for AVP with code {} and vendor-id {} ", avpCode,
                                    avpVendorId);
                    }
                }
            }

            addAvpDef(avpName, "N/A", vendorCode, Integer.valueOf(avpCode), avpMayEncrypt.equals("yes"), avpMandatory,
                      avpProtected, avpVendorBit, avpOriginalType, avpType,
                      groupedAvpChilds);
        }

        for (AvpRepresentation rep : avpMap.values()) {
            markWeaks((AvpRepresentationImpl) rep);
        }
    }

    private boolean markWeaks(AvpRepresentationImpl rep)
    {
        if (rep.isGrouped()) {
            boolean isWeak = false;
            for (AvpRepresentation repC : rep.getChildren()) {
                if (markWeaks((AvpRepresentationImpl) repC)) {
                    isWeak = true;
                }
            }
            rep.markWeak(isWeak);
        } else {
            rep.markWeak(rep.getCode() == -1);
        }

        return rep.isWeak();
    }

    /**
     * For a given AVP resolves the weak links (where AVP definition in grouped AVPs is not yet known, and only added by
     * Name)
     *
     * @param newAvp the AVP which was just defined
     */
    private void resolveWeakLinks(AvpRepresentation newAvp)
    {
        for (AvpRepresentation avp : avpMap.values()) {
            if (avp.isGrouped()) {
                if (avp.getName().equals(newAvp.getName())) {
                    continue;
                }
                List avpChilds = avp.getChildren();
                for (int n = 0; n < avpChilds.size(); n++) {
                    AvpRepresentation avpChild = avpChilds.get(n);
                    if (avpChild.getName().equals(newAvp.getName())) {
                        try {
                            AvpRepresentationImpl strongAvp = (AvpRepresentationImpl) newAvp.clone();
                            strongAvp.setMultiplicityIndicator(avpChild.getMultiplicityIndicator());
                            strongAvp.markFixPosition(avpChild.getPositionIndex());
                            strongAvp.markWeak(false);

                            avpChilds.set(n, strongAvp);

                            resolveWeakLinks(avp);
                        }
                        catch (CloneNotSupportedException cnse) {
                            // It should not happen, but anyway
                            if (logger.isWarnEnabled()) {
                                logger.warn("Unable to clone AVP " + newAvp, cnse);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @param doc
     * @param nameToCode
     * @param avpMap
     * @return
     */
    private void parseCommands(Document doc)
    {
        // here all grouped AVPs should have proper filling.
        // now lets go through message definition, we have to respect application nodes
        NodeList applicationNodes = doc.getElementsByTagName("application");

        // Map commandMap = new
        // HashMap();
        for (int applicationIndex = 0; applicationIndex < applicationNodes.getLength(); applicationIndex++) {
            if (applicationNodes.item(applicationIndex).getNodeType() == Node.ELEMENT_NODE) {
                Element applicationElement = (Element) applicationNodes.item(applicationIndex);

                if (!applicationElement.hasAttribute("id")) {
                    logger.debug("[ERROR] Application definition does not have ID, skipping message");
                    continue;
                }

                long applicationCode = Long.valueOf(applicationElement.getAttribute("id"));
                NodeList commandNodes = applicationElement.getElementsByTagName("command");

                for (int c = 0; c < commandNodes.getLength(); c++) {
                    Node commandNode = commandNodes.item(c);

                    if (commandNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element commandElement = (Element) commandNode;

                        if (!commandElement.hasAttribute("request")) {
                            logger.debug(
                                    "[ERROR] Command for application: {} does not define if its request or answer, skipping.",
                                    applicationCode);
                            continue;
                        }
                        String commandName = commandElement.getAttribute("name");
                        String commandCode = commandElement.getAttribute("code");

                        String isRequest = commandElement.getAttribute("request");

                        MessageRepresentationImpl msg = new MessageRepresentationImpl(Integer.valueOf(commandCode),
                                                                                      applicationCode,
                                                                                      Boolean.parseBoolean(isRequest), commandName);

                        Map commandAvpList = new HashMap();

                        commandMap.put(msg, msg);

                        // now we have to process avp defs for this message :)
                        NodeList commandAvpsList = commandElement.getElementsByTagName("avp");

                        for (int commandAvpIndex = 0; commandAvpIndex < commandAvpsList.getLength(); commandAvpIndex++) {
                            if (commandAvpsList.item(commandAvpIndex).getNodeType() == Node.ELEMENT_NODE) {
                                Element commandAvpElement = (Element) commandAvpsList.item(commandAvpIndex);
                                String multiplicity = null;
                                String name = null;
                                String index = null;
                                if (!commandAvpElement.hasAttribute("name")) {
                                    logger.debug(
                                            "[ERROR] Command defines avp without name! Command: {}, Code: {}, ApplicationID: {}",
                                            new Object[]{msg.getName(), msg.getCommandCode(), msg.getApplicationId()});
                                    continue;
                                } else {
                                    name = commandAvpElement.getAttribute("name");
                                }

                                if (!commandAvpElement.hasAttribute("multiplicity")) {
                                    logger.debug("[WARN] Command defines avp without multiplicity.");
                                    multiplicity = AvpRepresentation._MP_ZERO_OR_MORE;
                                } else {
                                    multiplicity = commandAvpElement.getAttribute("multiplicity");
                                }

                                index = commandAvpElement.hasAttribute("index") ? commandAvpElement.getAttribute("index")
                                                                                : "-1";

                                String avpCode = commandAvpElement.getAttribute("code");
                                String avpVendor = commandAvpElement.getAttribute("vendor");
                                if (avpCode == null) {
                                    logger.debug(
                                            "[ERROR] Command defines avp without code! Command: {}, Code: {}, ApplicationID: {}",
                                            new Object[]{msg.getName(), msg.getCommandCode(), msg.getApplicationId()});
                                    continue;
                                }
                                if (avpVendor == null) {
                                    logger.debug(
                                            "[WARN] Command defines avp without vendor, assuming default. Command: {}, Code: {}, ApplicationID: {}",
                                            new Object[]{msg.getName(), msg.getCommandCode(), msg.getApplicationId()});
                                    avpVendor = "0";
                                }

                                // here we have name and multiplicity. we have to get avp def from name, clone and set multiplicity.
                                AvpRepresentation strongRepresentation = null;
                                AvpRepresentation strongKey = getMapKey(Integer.valueOf(avpCode), Long.valueOf(avpVendor));

                                strongRepresentation = this.avpMap.get(strongKey);
                                if (strongRepresentation != null && !strongRepresentation.isWeak()) {
                                    AvpRepresentationImpl clone;
                                    try {
                                        clone = (AvpRepresentationImpl) strongRepresentation.clone();
                                        clone.setMultiplicityIndicator(multiplicity);
                                        clone.markFixPosition(Integer.valueOf(index));
                                        commandAvpList.put(clone, clone);
                                    }
                                    catch (CloneNotSupportedException cnse) {
                                        // It should not happen, but anyway
                                        if (logger.isWarnEnabled()) {
                                            logger.warn("Unable to clone AVP " + strongRepresentation, cnse);
                                        }
                                    }
                                } else {
                                    logger.debug("[WARN] No strong avp for key {}, in name: {}",
                                                 new Object[]{strongKey, name});
                                    continue;
                                }
                            }
                        }

                        msg.setMessageAvps(commandAvpList);
                    }
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#isConfigured()
     */
    @Override
    public boolean isConfigured()
    {
        return this.configured;
    }

    @Override
    public AvpRepresentation getAvp(int code)
    {
        return getAvp(code, 0);
    }

    @Override
    public AvpRepresentation getAvp(int code, long vendorId)
    {
        if (!this.configured) {
            return null;
        }
        AvpRepresentation avp = avpMap.get(getMapKey(code, vendorId));

        if (avp == null) {
            logger.warn("AVP with code {} and Vendor-Id {} not present in dictionary!", code, vendorId);
        }

        return avp;
    }

    @Override
    public AvpRepresentation getAvp(String avpName)
    {
        return this.configured ? avpByNameMap.get(avpName) : null;
    }

    private long getVendorCode(String vendorId)
    {
        long value = -1;

        if (vendorId == null) {
            value = 0;
        } else {
            String vendorCode = vendorMap.get(vendorId);
            value = vendorCode == null ? 0 : Long.parseLong(vendorCode);
        }

        return value;
    }

    private AvpRepresentation getMapKey(int avpCode, long vendorId)
    {
        return new AvpRepresentationImpl(avpCode, vendorId);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#getMessage(int, boolean)
     */
    @Override
    public MessageRepresentation getMessage(int commandCode, boolean isRequest)
    {
        return this.getMessage(commandCode, 0, isRequest);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#getMessage(int, long, boolean)
     */
    @Override
    public MessageRepresentation getMessage(int commandCode, long applicationId, boolean isRequest)
    {
        if (!this.configured) {
            return null;
        }
        MessageRepresentation key = new MessageRepresentationImpl(commandCode, applicationId, isRequest);
        return this.commandMap.get(key);
    }

    // Validation ---------------------------------------------------------------

    private boolean enabled = true;
    private ValidatorLevel sendValidationLevel = ValidatorLevel.ALL;
    private ValidatorLevel receiveValidationLevel = ValidatorLevel.OFF;

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#isValidate()
     */
    @Override
    public boolean isEnabled()
    {
        return this.enabled;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#getSendLevel()
     */
    @Override
    public ValidatorLevel getSendLevel()
    {
        return this.sendValidationLevel;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jdiameter.api.validation.Dictionary#getReceiveLevel()
     */
    @Override
    public ValidatorLevel getReceiveLevel()
    {
        return this.receiveValidationLevel;
    }

    @Override
    public void setSendLevel(ValidatorLevel level)
    {
        this.sendValidationLevel = level;
    }

    @Override
    public void setReceiveLevel(ValidatorLevel level)
    {
        this.receiveValidationLevel = level;
    }

    @Override
    public void setEnabled(boolean enabled)
    {
        this.enabled = enabled;
    }

    public void setConfigured(boolean configured)
    {
        this.configured = configured;
    }

    @Override
    public void validate(Message msg, boolean incoming) throws AvpNotAllowedException
    {
        if (!enabled || !configured) {
            return;
        }

        MessageRepresentationImpl rep = new MessageRepresentationImpl(msg.getCommandCode(), msg.getApplicationId(),
                                                                      msg.isRequest());
        rep = (MessageRepresentationImpl) this.commandMap.get(rep);
        if (rep == null) {
            // no notion, lets leave it.
            logger.warn("Validation could not be performed, command not defined!. Code={}, Application-Id={}, Req={}",
                        new Object[]{msg.getCommandCode(), msg.getApplicationId(), msg.isRequest()});
            return;
        }

        rep.validate(msg, (incoming ? receiveValidationLevel : sendValidationLevel));
    }

    // Helper methods -----------------------------------------------------------

    public Map getAvpMap()
    {
        return avpMap;
    }

    public Map getVendorMap()
    {
        return vendorMap;
    }

    public Map getCommandMap()
    {
        return commandMap;
    }

    public Map getTypedefMap()
    {
        return typedefMap;
    }

    public Map getNameToCodeMap()
    {
        return avpByNameMap;
    }

    protected void printAvpTree(AvpRepresentation rep, String tab)
    {
        String x = tab + "+-- " + rep.getCode() + "/" + rep.getVendorId();
        while (x.length() < 25) {
            x += ".";
        }
        System.out.println(x + rep.getName() + " > " + rep.getType());
        if (rep.isGrouped()) {
            for (AvpRepresentation repC : rep.getChildren()) {
                printAvpTree(repC, "  " + tab);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy