Package org.apache.qpid.client.url

Source Code of org.apache.qpid.client.url.URLParser_0_10

/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.qpid.client.url;

import org.apache.qpid.client.AMQBrokerDetails;
import org.apache.qpid.jms.BrokerDetails;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

/**
* The format Qpid URL is based on the AMQP one. The grammar is as follows:
* <p>
* <p>{@literal qpid_url          = "qpid:" [client_props "@"] port_addr_list ["/" future-parameters] }
* <p>{@literal port_addr_list    = [port_addr ","]* port_addr }
* <p>{@literal port_addr         = tcp_port_addr | tls_prot_addr | future_prot_addr }
* <p>{@literal tcp_port_addr     = tcp_id tcp_addr }
* <p>{@literal tcp_id            = "tcp:" | "" }
* <p>{@literal tcp_addr          = host [":" port] }
* <p>{@literal host              = <as per http://www.apps.ietf.org/> }
* <p>{@literal port              = number }
* <p>{@literal tls_prot_addr     = tls_id tls_addr }
* <p>{@literal tls_id            = "tls:" | "" }
* <p>{@literal tls_addr          = host [":" port] }
* <p>{@literal future_prot_addr  = future_prot_id future_prot_addr }
* <p>{@literal future_prot_id    = <placeholder, must end in ":". Example "sctp:"> }
* <p>{@literal future_prot_addr  = <placeholder, protocl-specific address> }
* <p>{@literal future_parameters = <placeholder, not used in failover addresses> }
* <p>{@literal client_props      = [client_prop ";"]*  client_prop }
* <p>{@literal client_prop       = prop "=" val }
* <p>{@literal prop              = chars as per <as per http://www.apps.ietf.org/> }
* <p>{@literal val               = valid as per <as per http://www.apps.ietf.org/> }
* <p>
* Ex:
* <p>
* {@literal qpid:virtualhost=tcp:host-foo,test,client_id=foo@tcp:myhost.com:5672,virtualhost=prod;
* keystore=/opt/keystore@client_id2@tls:mysecurehost.com:5672 }
*/
public class URLParser_0_10
{
    private static final char[] URL_START_SEQ = new char[]{'q', 'p', 'i', 'd', ':'};
    private static final char PROPERTY_EQUALS_CHAR = '=';
    private static final char PROPERTY_SEPARATOR_CHAR = ';';
    private static final char ADDRESS_SEPERATOR_CHAR = ',';

    private static final char TRANSPORT_HOST_SEPARATOR_CHAR = ':';
    private static final char HOST_PORT_SEPARATOR_CHAR = ':';
    private static final char AT_CHAR = '@';
    private static final char END_OF_URL_MARKER = '^';

    enum URLParserState
    {
        QPID_URL_START,
        ADDRESS_START,
        PROPERTY_NAME,
        PROPERTY_EQUALS,
        PROPERTY_VALUE,
        PROPERTY_SEPARATOR,
        AT_CHAR,
        TRANSPORT,
        TRANSPORT_HOST_SEPARATOR,
        HOST,
        HOST_PORT_SEPARATOR,
        PORT,
        ADDRESS_END,
        ADDRESS_SEPERATOR,
        QPID_URL_END,
        ERROR
    }

    //-- Constructors

    private char[] _url;
    private List<BrokerDetails> _brokerDetailList = new ArrayList<BrokerDetails>();
    private String _error;
    private int _index = 0;
    private BrokerDetails _currentBroker;
    private String _currentPropName;
    private boolean _endOfURL = false;
    private URLParserState _currentParserState;

    public URLParser_0_10(String url) throws MalformedURLException
    {
        _url = (url + END_OF_URL_MARKER).toCharArray();
        _endOfURL = false;
        _currentParserState = URLParserState.QPID_URL_START;
        URLParserState prevState = _currentParserState; // for error handling
        try
        {
            while (_currentParserState != URLParserState.ERROR && _currentParserState != URLParserState.QPID_URL_END)
            {
                prevState = _currentParserState;
                _currentParserState = next();
            }

            if (_currentParserState == URLParserState.ERROR)
            {
                _error =
                        "Invalid URL format [current_state = " + prevState + ", broker details parsed so far " + _currentBroker + " ] error at (" + _index + ") due to " + _error;
                MalformedURLException ex;
                ex = new MalformedURLException(_error);
                throw ex;
            }
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            _error = "Invalid URL format [current_state = " + prevState + ", broker details parsed so far " + _currentBroker + " ] error at (" + _index + ")";
            MalformedURLException ex = new MalformedURLException(_error);
            throw ex;
        }
    }

    //-- interface QpidURL
    public List<BrokerDetails> getAllBrokerDetails()
    {
        return _brokerDetailList;
    }

    public String getURL()
    {
        return new String(_url);
    }

    private URLParserState next()
    {
        switch (_currentParserState)
        {
            case QPID_URL_START:
                return checkSequence(URL_START_SEQ, URLParserState.ADDRESS_START);
            case ADDRESS_START:
                return startAddress();
            case PROPERTY_NAME:
                return extractPropertyName();
            case PROPERTY_EQUALS:
                _index++; // skip the equal sign
                return URLParserState.PROPERTY_VALUE;
            case PROPERTY_VALUE:
                return extractPropertyValue();
            case PROPERTY_SEPARATOR:
                _index++; // skip ","
                return URLParserState.PROPERTY_NAME;
            case AT_CHAR:
                _index++; // skip the @ sign
                return URLParserState.TRANSPORT;
            case TRANSPORT:
                return extractTransport();
            case TRANSPORT_HOST_SEPARATOR:
                _index++; // skip ":"
                return URLParserState.HOST;
            case HOST:
                return extractHost();
            case HOST_PORT_SEPARATOR:
                _index++; // skip ":"
                return URLParserState.PORT;
            case PORT:
                return extractPort();
            case ADDRESS_END:
                return endAddress();
            case ADDRESS_SEPERATOR:
                _index++; // skip ","
                return URLParserState.ADDRESS_START;
            default:
                return URLParserState.ERROR;
        }
    }

    private URLParserState checkSequence(char[] expected, URLParserState nextPart)
    {
        for (char expectedChar : expected)
        {
            if (expectedChar != _url[_index])
            {
                _error = "Excepted (" + expectedChar + ") at position " + _index + ", got (" + _url[_index] + ")";
                return URLParserState.ERROR;
            }
            _index++;
        }
        return nextPart;
    }

    private URLParserState startAddress()
    {
        _currentBroker = new AMQBrokerDetails();

        for (int j = _index; j < _url.length; j++)
        {
            if (_url[j] == PROPERTY_EQUALS_CHAR)
            {
                return URLParserState.PROPERTY_NAME;
            }
            else if (_url[j] == ADDRESS_SEPERATOR_CHAR)
            {
                return URLParserState.TRANSPORT;
            }
        }
        return URLParserState.TRANSPORT;
    }

    private URLParserState endAddress()
    {
        _brokerDetailList.add(_currentBroker);
        if (_endOfURL)
        {
            return URLParserState.QPID_URL_END;
        }
        else
        {
            return URLParserState.ADDRESS_SEPERATOR;
        }
    }

    private URLParserState extractPropertyName()
    {
        StringBuilder b = new StringBuilder();
        char next = _url[_index];
        while (next != PROPERTY_EQUALS_CHAR && next != AT_CHAR)
        {
            b.append(next);
            next = _url[++_index];
        }
        _currentPropName = b.toString();
        if (_currentPropName.trim().equals(""))
        {
            _error = "Property name cannot be empty";
            return URLParserState.ERROR;
        }
        else if (next == PROPERTY_EQUALS_CHAR)
        {
            return URLParserState.PROPERTY_EQUALS;
        }
        else
        {
            return URLParserState.AT_CHAR;
        }
    }

    private URLParserState extractPropertyValue()
    {
        StringBuilder b = new StringBuilder();
        char next = _url[_index];
        while (next != PROPERTY_SEPARATOR_CHAR && next != AT_CHAR)
        {
            b.append(next);
            next = _url[++_index];
        }
        String propValue = b.toString();
        if (propValue.trim().equals(""))
        {
            _error = "Property values cannot be empty";
            return URLParserState.ERROR;
        }
        else
        {
            _currentBroker.setProperty(_currentPropName, propValue);
            if (next == PROPERTY_SEPARATOR_CHAR)
            {
                return URLParserState.PROPERTY_SEPARATOR;
            }
            else
            {
                return URLParserState.AT_CHAR;
            }
        }
    }

    private URLParserState extractTransport()
    {
        String transport = buildUntil(TRANSPORT_HOST_SEPARATOR_CHAR);
        if (transport.trim().equals(""))
        {
            _error = "Transport cannot be empty";
            return URLParserState.ERROR;
        }
        else if (!(transport.trim().equals(BrokerDetails.PROTOCOL_TCP) || transport.trim()
                .equals(BrokerDetails.PROTOCOL_TLS)))
        {
            _error = "Transport cannot be " + transport + " value must be tcp or tls";
            return URLParserState.ERROR;
        }
        else
        {
            _currentBroker.setTransport(transport);
            return URLParserState.TRANSPORT_HOST_SEPARATOR;
        }
    }

    private URLParserState extractHost()
    {
        char nextSep = 'c';
        String host;
        URLParserState nextState;

        for (int i = _index; i < _url.length; i++)
        {
            if (_url[i] == HOST_PORT_SEPARATOR_CHAR)
            {
                nextSep = HOST_PORT_SEPARATOR_CHAR;
                break;
            }
            else if (_url[i] == ADDRESS_SEPERATOR_CHAR)
            {
                nextSep = ADDRESS_SEPERATOR_CHAR;
                break;
            }
        }

        if (nextSep == HOST_PORT_SEPARATOR_CHAR)
        {
            host = buildUntil(HOST_PORT_SEPARATOR_CHAR);
            nextState = URLParserState.HOST_PORT_SEPARATOR;
        }
        else if (nextSep == ADDRESS_SEPERATOR_CHAR)
        {
            host = buildUntil(ADDRESS_SEPERATOR_CHAR);
            nextState = URLParserState.ADDRESS_END;
        }
        else
        {
            host = buildUntil(END_OF_URL_MARKER);
            nextState = URLParserState.ADDRESS_END;
            _endOfURL = true;
        }

        if (host.trim().equals(""))
        {
            _error = "Host cannot be empty";
            return URLParserState.ERROR;
        }
        else
        {
            _currentBroker.setHost(host);
            return nextState;
        }
    }


    private URLParserState extractPort()
    {

        StringBuilder b = new StringBuilder();
        try
        {
            char next = _url[_index];
            while (next != ADDRESS_SEPERATOR_CHAR && next != END_OF_URL_MARKER )
            {
                b.append(next);
                next = _url[++_index];
            }
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            _endOfURL = true;
        }
        String portStr = b.toString();
        if (portStr.trim().equals(""))
        {
            _error = "Host cannot be empty";
            return URLParserState.ERROR;
        }
        else
        {
            try
            {
                int port = Integer.parseInt(portStr);
                _currentBroker.setPort(port);
                if( _url[_index] == END_OF_URL_MARKER )
                {
                    _endOfURL = true;
                }
                return URLParserState.ADDRESS_END;
            }
            catch (NumberFormatException e)
            {
                _error = "Illegal number for port";
                return URLParserState.ERROR;
            }
        }
    }

    private String buildUntil(char c)
    {
        StringBuilder b = new StringBuilder();
        char next = _url[_index];
        while (next != c)
        {
            b.append(next);
            next = _url[++_index];
        }
        return b.toString();
    }

    public static void main(String[] args)
    {
        String testurl = "qpid:password=pass;username=name@tcp:test1";
        try
        {
            URLParser_0_10 impl = new URLParser_0_10(testurl);
            for (BrokerDetails d : impl.getAllBrokerDetails())
            {
                System.out.println(d);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
TOP

Related Classes of org.apache.qpid.client.url.URLParser_0_10

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.