Package com.ericsson.ssa.sip

Source Code of com.ericsson.ssa.sip.SipURIImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.sip;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.UnsupportedEncodingException;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipURI;


/**
* @author ekrigro
* @reviewed qmigkra 2006-nov-17
*/
public class SipURIImpl extends URIImpl implements SipURI, Externalizable {
    /**
     *
     */
    private static final long serialVersionUID = 3616450094292218936L;
    static String DUPLICATE_PARAM = "The parsed SIP URI has two parameter with the same name : ";
    public static final String LOOSE_ROUTE_PARAM = "lr";
    public static final String MADDR_PARAM = "maddr";
    public static final String METHOD_PARAM = "method";
    public static final String TTL_PARAM = "ttl";
    public static final String TRANSPORT_PARAM = "transport";
    public static final String USER_PARAM = "user";
    public static final String FRAGID_PARAM = "fid";
    private static SipURIDecoder _uriDecoder = new SipURIDecoder();
    private static SipURIEncoder _uriEncoder = new SipURIEncoder();
    private boolean _secure = false;
    private Ascii7String _user = null;
    private Ascii7String _password = null;
    private Ascii7String _host = null;
    private int _port = -1;
   
    /**
     * Special handling of SipURI for Contact Header.
     * If an Application retrieves a Contact header by calling getAddressHeader("Contact").getUri(),
     * the flag isModifingContactUri is set to true. In this mode the SipUri imposes restriction to
     * modify parts of the URI so that.
     *
     * 1. Set the user part of the uri.
     * 2. Set parameters, except for "method", "ttl", "maddr" and "lr" 
     * 3. 200 OK as response to an OPTIONS allows the application to set alternative names and
     *    methods to reach the user.
     *
     */
    //private boolean isModifingContactUri = false;

    // private ParameterByteMap     _parameters       = null;
    private ParameterByteMap _headers = null;

    public SipURIImpl() {
    } // used only in parser and serialization

    public SipURIImpl(boolean secure, String user, String host) {
        _secure = secure;
        _user = new Ascii7String(user);
        _host = new Ascii7String(host);
    }

    public SipURIImpl(String protocol, String uri, int offset)
        throws ServletParseException {
        if (protocol.equals(SipFactoryImpl.SIPS_URI_PROTOCOL)) {
            _secure = true;
        }

        try {
            parse(uri, offset, uri.length());
        } catch (RuntimeException e) {
            throw new ServletParseException(
                "Unexpected exception while parsing URI: " + e);
        }
    }

    // For RMI serialization
    public void writeExternal(ObjectOutput output) throws IOException {
        try {
            // _secure, _user, _password, _host, _port, _parameters, _headers
            output.writeBoolean(_secure);

            if (_user != null) { // Special treatment since it can be null and writeUTF can't be used
                output.writeInt(_user.length());
                output.write(_user.getBytes());
            } else {
                output.writeInt(0);
            }

            if (_password != null) {
                output.writeInt(_password.length());
                output.write(_password.getBytes());
            } else {
                output.writeInt(0);
            }

            output.writeUTF(_host.toString());
            output.writeInt(_port);

            if (_parameters != null && _parameters.toArray() != null) {
                byte[] parameter_data = _parameters.toArray();
                output.writeInt(parameter_data.length); // write #bytes
                output.write(parameter_data);
            } else {
                output.writeInt(0);
            }

            if (_headers != null && _headers.toArray() != null) {
                byte[] headers_data = _headers.toArray();
                output.writeInt(headers_data.length); // write #bytes
                output.write(headers_data);
            } else {
                output.writeInt(0);
            }
        } catch (Exception ignore) {
        }
    }

    public void readExternal(ObjectInput input) throws IOException {
        try {
            _secure = input.readBoolean();

            int len = input.readInt();

            if (len > 0) {
                byte[] b = new byte[len];
                input.read(b);
                _user = new Ascii7String(b);
            }

            len = input.readInt();

            if (len > 0) {
                byte[] b = new byte[len];
                input.read(b);
                _password = new Ascii7String(b);
            }

            _host = new Ascii7String(input.readUTF());
            _port = input.readInt();

            len = input.readInt(); // read parameter #bytes
            if (len > 0) {
                byte[] parameter_data = new byte[len];
                int readBytes = input.read(parameter_data, 0, len);

                if (readBytes != len) {
                throw new IOException("failed to read parameter section len:" +
                    len);
                }
                _parameters = new ParameterByteMap(parameter_data, ';');
            }
           
            len = input.readInt(); // read headers #bytes
            if (len > 0) {
                byte[] headers_data = new byte[len];
                int readBytes = input.read(headers_data, 0, len);
   
                if (readBytes != len) {
                    throw new IOException("failed to read headers section len:" +
                        len);
                }
   
                _headers = new ParameterByteMap(headers_data, ';');
            }
        } catch (Exception ignore) {
        }
    }

    private void parse(String str, int offset, int length)
        throws ServletParseException {
        int passwdIndex = -1; // colon
        int portIndex = -1; // colon
        int semiIndex = -1;
        int qIndex = -1;
        int atIndex = -1;
        int endHostIndex = length;
        int endParamIndex = length;

        for (int i = offset; i < length; i++) {
            // Control character should not appear in the url.
            if (Character.isISOControl(str.charAt(i))) {
                throw new ServletParseException(
                    "The URI contains a control character.");
            }

            if (str.charAt(i) == ':' && semiIndex == -1 ) {
                if (atIndex > 0) {
                    portIndex = i;
                } else {
                    passwdIndex = i;
                }
            } else if ((atIndex == -1) && (str.charAt(i) == '@')) {
                atIndex = i;
            } else if ((semiIndex == -1) && (str.charAt(i) == ';')) {
                semiIndex = i;
                endHostIndex = i;
            } else if ((semiIndex != -1) && (str.charAt(i) == ';') && semiIndex < atIndex ) {
                semiIndex = i;
                endHostIndex = i;
            } else if (str.charAt(i) == '?') {
                qIndex = i;

                if (semiIndex > 0) {
                    endParamIndex = i;
                } else {
                    endHostIndex = i;
                }

                break;
            }
        }

        if ((passwdIndex > 0) && (atIndex < 0)) {
            portIndex = passwdIndex;
        }

        /*
         * INFO: The user part and parameter parts of the url, could contains
         * escaped characters, so we need to unecape them.
         */

        // Check user
        try {
            if (atIndex > 0) {
                if (passwdIndex > 0) {
                    _user = new Ascii7String(str.substring(offset,
                            passwdIndex));
                    _password = new Ascii7String(str.substring(passwdIndex + 1,
                            atIndex));
                } else {
                    _user = new Ascii7String(str.substring(offset, atIndex));
                }

                offset = atIndex + 1;
            }
 
            // Ex: "sip:+302106699011;tgrp=0;trunk-context=0@164.48.135.94:5060"
            if ( endHostIndex < offset ) {
                endHostIndex = str.length();
                String host = str.substring(offset, endHostIndex);
                int innerCheck =host.indexOf(":");
                if ( innerCheck != -1 )
                    portIndex = offset + innerCheck;
            }
            // Now the hostpart that is mandatory
            if (portIndex > 0) { // Host n port
                _host = new Ascii7String(str.substring(offset, portIndex));
                _port = Integer.parseInt(str.substring(portIndex + 1,
                        endHostIndex));
            } else { // no port only host
                _host = new Ascii7String(str.substring(offset,
                        endHostIndex));
            }
        } catch (IllegalStateException e) {
            throw new ServletParseException("CharacterCodingException");
        }

        offset = endHostIndex + 1;

        // Time for the parameters
        if (semiIndex > 0) {
            int numBytes = endParamIndex - semiIndex;
            _parameters = new ParameterByteMap(str.getBytes(), semiIndex,
                    numBytes,
                    ';');
        }

        // And last and least the headers
        if (qIndex > 0) {
            int endIndex = length - 1;
            int numBytes = endIndex - qIndex;
            _headers =
                    new ParameterByteMap(str.getBytes(), qIndex, numBytes + 1,
                    '&');
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getUser()
     */
    public String getUser() {
        try {
            if (_user == null) {
                return null;
            }

            return _uriDecoder.decode(_user.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setUser(java.lang.String)
     */
    public void setUser(String user) {
        verify();
        if (user != null && user.trim().length()>0) {
            _user = new Ascii7String(_uriEncoder.encodeUserPart(user));
        } else {
            _user = null;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getUserPassword()
     */
    public String getUserPassword() {
        try {
            if (_password == null) {
                return null;
            }

            return _uriDecoder.decode(_password.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setUserPassword(java.lang.String)
     */
    public void setUserPassword(String passwd) {
        verify();
        if (passwd != null && passwd.trim().length()>0) {
            _password = new Ascii7String(_uriEncoder.encodePasswordPart(passwd));
        }
        else {
           _password = null;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getHost()
     */
    public String getHost() {
        return _host.toString();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setHost(java.lang.String)
     */
    public void setHost(String host) {
        verify();
        __setHost(host);
    }

    void __setHost(String host) {
        _host = new Ascii7String(host);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getPort()
     */
    public int getPort() {
        return _port;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setPort(int)
     */
    public void setPort(int port) {
        verify();
        __setPort(port);
    }


    void __setPort(int port) {
        if (port < 0) {
            _port = -1;
        } else {
            _port = port;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#isSecure()
     */
    public boolean isSecure() {
        return _secure;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setSecure(boolean)
     */
    public void setSecure(boolean sec) {
        verify();
        _secure = sec;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getTransportParam()
     */
    public String getTransportParam() {
        return getParameter(TRANSPORT_PARAM);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setTransportParam(java.lang.String)
     */
    public void setTransportParam(String value) {

        setParameter(TRANSPORT_PARAM, value);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getMAddrParam()
     */
    public String getMAddrParam() {
        return getParameter(MADDR_PARAM);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setMAddrParam(java.lang.String)
     */
    public void setMAddrParam(String value) {
        setParameter(MADDR_PARAM, value);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getMethodParam()
     */
    public String getMethodParam() {
        return getParameter(METHOD_PARAM);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setMethodParam(java.lang.String)
     */
    public void setMethodParam(String value) {
        setParameter(METHOD_PARAM, value);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getTTLParam()
     */
    public int getTTLParam() {
        int ttl = -1;
        String value = getParameter(TTL_PARAM);

        if (value != null) {
            try {
                ttl = Integer.parseInt(value);
            } catch (Exception e) {
            } // Bad luck :-)
        }

        return ttl;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setTTLParam(int)
     */
    public void setTTLParam(int value) {
        setParameter(TTL_PARAM, String.valueOf(value));
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getUserParam()
     */
    public String getUserParam() {
        return getParameter(USER_PARAM);
    }
   
    @Override
    public void setParameter(String name, String value) {
        super.setParameter(name, value);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setUserParam(java.lang.String)
     */
    public void setUserParam(String value) {
        setParameter(USER_PARAM, value);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setLrParam(boolean)
     */
    public void setLrParam(boolean lr) {
        if (lr) {
            setParameter(LOOSE_ROUTE_PARAM, "");
        } else {
            removeParameter(LOOSE_ROUTE_PARAM);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getHeader(java.lang.String)
     */
    public String getHeader(String header) {
        if (_headers == null) {
            return null;
        }

        return _headers.get(header);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#setHeader(java.lang.String,
     *      java.lang.String)
     */
    public void setHeader(String header, String value) {
        verify();
        if (_headers == null) {
            _headers = new ParameterByteMap('&');
        }

        _headers.put(header, value);
    }

    public void removeHeader(String name) {
        verify();
        if (_headers != null) {
            _headers.remove(name);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.SipURI#getHeaderNames()
     */
    public Iterator<String> getHeaderNames() {
        if (_headers == null) {
            return Collections.EMPTY_LIST.iterator();
        }

        return _headers.getKeys();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.URI#getScheme()
     */
    public String getScheme() {
        return _secure ? SipFactoryImpl.SIPS_URI_PROTOCOL
                       : SipFactoryImpl.SIP_URI_PROTOCOL;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.sip.URI#isSipURI()
     */
    public boolean isSipURI() {
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#clone()
     */
    public SipURIImpl clone() {
        SipURIImpl newUri = new SipURIImpl();
        newUri._secure = _secure;
        // avoid String(String) due to memory overhead when a explicit copy is
        // created
        // copies is Unnecesary because String are immutable!!
        // if (_user != null) newUri._user = new String(_user);
        // if (_password != null) newUri._password = new String(_password);
        // if (_host != null) newUri._host = new String(_host);
        newUri._user = _user;
        newUri._password = _password;
        newUri._host = _host;
        newUri._port = _port;

        if (_parameters != null) {
            newUri._parameters = (ParameterByteMap) _parameters.clone();
            // remove tag Due to strange requirement on Address to not clone tag
            newUri._parameters.remove(AddressImpl.TAG_PARAM);
        }

        if (_headers != null) {
            newUri._headers = (ParameterByteMap) _headers.clone();
        }

        return newUri;
    }

    /*
     * RFC3261 19.1.4
     *
     *
     *
     * - Comparison of the userinfo of SIP and SIPS URIs is case-sensitive
     *
     * - The ordering of parameters and header fields is not significant
     *   in comparing SIP and SIPS URIs.
     *
     * - Characters other than those in the "reserved" set (RFC 2396)
     *   are equivalent to their ""%" HEX HEX" encoding.
     *
     * - An IP address that is the result of a DNS lookup of a host name
     *   does not match that host name
     *
     * -
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(Object o) {
        if (!(o instanceof SipURI)) {
            return false;
        }

        SipURI uri = (SipURI) o;

        if (_port != uri.getPort()) {
            return false;
        }

        if (_secure != uri.isSecure()) {
            return false;
        }

        if (((_user == null) && (uri.getUser() != null)) ||
                ((_user != null) && (uri.getUser() == null))) {
            return false;
        }

        if ((_user != null) && !getUser().equals(uri.getUser())) {
            return false;
        }

        if (((_password == null) && (uri.getUserPassword() != null)) ||
                ((_password != null) && (uri.getUserPassword() == null))) {
            return false;
        }

        if ((_password != null) &&
                !getUserPassword().equals(uri.getUserPassword())) {
            return false;
        }

        if (  ( (getHost() == null) && (uri.getHost() != null) ) ||
              ( (uri.getHost() == null) &&  (this.getHost() == null))   ) {
            return false;
        }
       
        if (getHost() != null && uri.getHost() != null && !getHost().equalsIgnoreCase(uri.getHost()) ) {
            return false;
        }

        // Compare headers
        HashMap<String,String> thisHeaders = new HashMap<String,String>();
        Iterator<String> thisHeaderIterator = getHeaderNames();
        while (thisHeaderIterator.hasNext()) {
            String key = (String) thisHeaderIterator.next();
            thisHeaders.put(key,this.getHeader(key));
        }
       
        HashMap<String,String> uriHeaders = new HashMap<String,String>();
        Iterator<String> uriHeaderIterator = uri.getHeaderNames();
        while (uriHeaderIterator.hasNext()) {
            String key = (String) uriHeaderIterator.next();
            uriHeaders.put(key, uri.getHeader(key));
        }
       
        if ( !thisHeaders.equals(uriHeaders) ) {
            return false;
        }
       
        // Compare parameters
        Map<String,String> thisParameters = new HashMap<String,String>(8);
        Iterator<String> thisParameterIterator = getParameterNames();
        while (thisParameterIterator.hasNext()) {
            String key = (String) thisParameterIterator.next();
            //adding keys lowercase and values as normal
            thisParameters.put(key.toLowerCase(), this.getParameter(key));
        }
       
        Map<String,String> uriParameters = new HashMap<String,String>(8);
        Iterator<String> uriParameterIterator = uri.getParameterNames();
        while (uriParameterIterator.hasNext()) {
            String key = (String) uriParameterIterator.next();
            //adding keys lowercase and values as normal
            uriParameters.put(key.toLowerCase(), uri.getParameter(key));
        }
       
        if (compareParameters(thisParameters, uriParameters)) {
            //swap and compare from the other collection point of view, since after iteration the second collection may contains special parameters, such as TTL
            return compareParameters(uriParameters, thisParameters);
        }
        return false;
    }
   
    /**
     * Comparing parameters in the URI According to 19.1.4 URI Comparison comparing parameters
     * @param sourceParams
     * @param destParams
     * @return
     */
    private boolean compareParameters(Map<String, String> sourceParams, Map<String, String> destParams) {
        //� Any uri-parameter appearing in both URIs must match. If they are not existing on both, then ignore comparing them
        Iterator<String> keysIterator = sourceParams.keySet().iterator();
        while (keysIterator.hasNext()) {
            String srcKey = keysIterator.next();
           
            //special handling for MADDR_PARAM, TTL_PARAM, they must exists with same values
            if (srcKey.equals(MADDR_PARAM) || srcKey.equals(TTL_PARAM) || srcKey.equals(TRANSPORT_PARAM)
                    || srcKey.equals(USER_PARAM) || srcKey.equals(METHOD_PARAM)) {
                if (!destParams.containsKey(srcKey) || !sourceParams.get(srcKey).toLowerCase().equals(destParams.get(srcKey).toLowerCase())) {
                    return false;
                }
                else {
                    //remove it so we can compare the dest to src and not comparing these two next time
                    keysIterator.remove();
                    destParams.remove(srcKey);
                }
            } else {
           
                //if there is a key, lets compare the values non case sensitive
                if (destParams.containsKey(srcKey)) {
                    if (!sourceParams.get(srcKey).toLowerCase().equals(destParams.get(srcKey).toLowerCase())) {
                        return false;
                    }
                    else {
                        //remove it so we can compare the dest to src and not comparing these two next time
                        keysIterator.remove();
                        destParams.remove(srcKey);
                    }
                }
            }
        }
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    public int hashCode() {
        // Not all needs to be unique
        // A ^ (((B >> 16) & 0x0000FFFF) | ((B<<16) & 0xFFFF0000))
        // Or try just ^ if this is to slow
        int result = _host.hashCode() ^ _port;

        if (_user != null) {
            result = _user.hashCode() ^ result;
        }

        return result;
    }

    /*
     * Build up the sip uri. If the user or the parameter part contains any
     * unescaped characters then escape them.
     *
     * @see java.lang.Object#toString()
     */
    public String toString() {
        StringBuilder sb = new StringBuilder(getScheme());
        sb.append(':');

        if (_user != null) {
            sb.append(_user.toString());

            if (_password != null) {
                sb.append(':');
                sb.append(_password.toString());
            }

            sb.append('@');
        }

        sb.append(_host.toString());

        if (_port > 0) {
            sb.append(':');
            sb.append(_port);
        }

        // Duplicated in AddressImpl
        if (_parameters != null) {
            sb.append(_parameters.toString());
        }

        if (_headers != null) {
            sb.append(_headers.toString());
        }

        return sb.toString();
    }

    void removeToTag() {
        if (_parameters != null) {
            _parameters.remove(AddressImpl.TAG_PARAM);
        }
    }
   



}
TOP

Related Classes of com.ericsson.ssa.sip.SipURIImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.