Package flex.messaging.services.messaging.selector

Source Code of flex.messaging.services.messaging.selector.JMSSelector

/*
* @(#)JMSSelector.java 1.28 00/11/16
*
* Copyright 1999-2000 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package flex.messaging.services.messaging.selector;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.StringTokenizer;

import flex.messaging.MessageException;
import flex.messaging.log.LogCategories;
import flex.messaging.messages.Message;

/**
* Provides JMS selector capability to a MessageConsumer.
*
* Uses a SQL parser written in SQLParser.jj
*
* @author Farrukh Najmi
* @exclude
*/
public class JMSSelector
{
    public static final String LOG_CATEGORY = LogCategories.MESSAGE_SELECTOR; // Because we're not always JMS-specific.
    private static final int PARSE_FAILURE = 10600;
    private static final int BAD_TYPE_COMPARISON = 10601;
    private static final int PARSER_ERROR = 10602;
    static final boolean debug = false;

    SQLParser   parser;
    String      pattern;
    Message     msg;

    /**
     * Class Constructor.
     *
     * @param pattern
     */
    public JMSSelector(String pattern)
    {
        if (pattern == null)
        {
            pattern = "";
        }

        //reason for passing the msg is to prevent dependency on com.sun.jms.*
        this.msg = null;
        this.pattern = pattern;
        InputStream stream = new ByteArrayInputStream(pattern.getBytes());

        parser = new SQLParser(this, stream);
    }

    /**
     * Returns the pattern used by this selector.
     *
     */
    public String getPattern()
    {
        return pattern;
    }

    /**
     * Sets the pattern that will be used by this selector to perform matches
     * Must conform to SQL-92 specification for a SQL pattern.
     */
    public void setPattern(String p)
    {
        pattern = p;
        InputStream stream = new ByteArrayInputStream(pattern.getBytes());

        parser.ReInit(stream);
        try
        {
            match(msg);
        }
        catch (MessageException me)
        {
            throw me;
        }
        catch (Throwable t)
        {
            throw new MessageException(t);
        }
    }

    /**
     * Matches the message against the selector expression.
     *
     * @param msg The message to match against.
     * @return true if the message headers match the selector; otherwise false.
     * @exception JMSSelectorException
     */
    public boolean match(Message msg)
    {
        boolean matched = false;
        if (pattern.equals(""))
        {
            matched = true;     // No selector
        }
        else
        {
            try
            {
                matched = parser.match(msg);
            }
            catch (ParseException pex)
            {
                JMSSelectorException jmse = new JMSSelectorException();
                jmse.setMessage(PARSE_FAILURE, new Object[] {pattern, pex.getMessage()});
                throw jmse;
            }
            catch (ClassCastException cce)
            {
                JMSSelectorException jmse = new JMSSelectorException();
                jmse.setMessage(BAD_TYPE_COMPARISON, new Object[] {pattern});
                throw jmse;
            }
            catch (Error err)
            {
                JMSSelectorException jmse = new JMSSelectorException();
                jmse.setMessage(PARSER_ERROR, new Object[] {pattern, err.getMessage()});
                throw jmse;
            }
            finally
            {
                InputStream stream = new ByteArrayInputStream(pattern.getBytes());
                parser.ReInit(stream);
            }
        }
        return matched;
    }

    /**
     * Used to determine selector match in a SQL LIKE expression. For example:
     * <pre>
     * str LIKE patternStr [ESCAPE escapeChar]
     * </pre>
     *
     * @param patternStr The pattern used in SQL LIKE statement
     * @param str The string being compared with patternStr in SQL LIKE statement
     * @param escapeChar The escape character used to treat wildcards '_' and '%' as normal
     *
     * @return <code>true</code> if the string matches the pattern; otherwise false.
     */
    boolean matchPattern(String patternStr, String str, char escapeChar)
    {
        boolean matched = false;
        String escapeCharStr = String.valueOf(escapeChar);
        String wildCards = "_%";
        String delims = wildCards + escapeCharStr;
        boolean escaped = false;
        int     index = 0;
        String  tok = null;

        try
        {
            if (debug)
            {
                System.err.println("JMSSelector:matchPattern patternStr = \'" + patternStr + "\' str = \'" + str + "\'");
            }
            if (str != null)
            {
                StringTokenizer st = new StringTokenizer(patternStr, delims, true);

                // Parse string into a Collection of tokens since we will need
                // to peek forward as we
                // scan tokens
                ArrayList tokens = new ArrayList();
                int k = 1;
                while (st.hasMoreTokens())
                {
                    tok = st.nextToken();
                    if (debug)
                    {
                        System.err.println(k++ + " matchPattern Token=" + tok);
                    }
                    tokens.add(tok);
                }

                matched = true;

                // Iterate over tokens list and match each token with str
                int numTokens = tokens.size();
                for (int i = 0; i < numTokens; i++)
                {
                    tok = (String)tokens.get(i);

                    // Token can be a delimeter or actual token
                    if (tok.equals(escapeCharStr) && (!escaped))
                    {
                        // Remember that the next character in patterStr must be
                        // treated literally
                        escaped = true;
                    }
                    else if (tok.equals("%") && (!escaped))
                    {
                        if (i == (numTokens - 1))
                        {
                            // wildcard is last character in pattern,
                            // match entire string.
                            index = str.length();
                        }
                        else if (i != numTokens - 1)
                        { // There are more tokens. If not then we have a
                            // match

                            // Now scan forward
                            int _cnt = 0; // count of '_' delimeters
                                            // encountered
                            ++i;
                            for (; i < numTokens; i++)
                            {
                                tok = (String)tokens.get(i);

                                if (tok.equals(escapeCharStr) && (!escaped))
                                {
                                    // Remember that the next character in
                                    // patterStr must be treated literally
                                    escaped = true;
                                }
                                else if (tok.equals("%") && (!escaped))
                                {
                                    // % followed by % is same as %
                                }
                                else if (tok.equals("_") && (!escaped))
                                {
                                    ++_cnt;
                                }
                                else
                                {
                                    // This is the nextNonDelimTok
                                    int oldIndex = index;

                                    if (i == (numTokens - 1))
                                    {
                                        // Not a general purpose fix for
                                        // wildcard matching bug.
                                        // At least handle case when
                                        // only one wildcard in pattern
                                        // that has a group of characters
                                        // trailing it.
                                        if (str.endsWith(tok))
                                        {
                                            index = str.length() - tok.length();
                                        }
                                        else
                                        {
                                            matched = false;
                                            if (debug)
                                            {
                                                System.err.println("no matched5 for token: '" + tok + "'");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        index = str.indexOf(tok, index);
                                    }

                                    if (index < 0)
                                    {
                                        matched = false;
                                        if (debug)
                                        {
                                            System.err.println("no matched1 for token: '" + tok + "'");
                                        }
                                    }
                                    else
                                    {
                                        // Make sure that we have _cnt
                                        // charecters between old index and new
                                        // index
                                        if (index - oldIndex >= _cnt)
                                        {
                                            index += tok.length();
                                            if (debug)
                                            {
                                                System.err.println("matched1: " + str.substring(0, index));
                                            }
                                        }
                                        else
                                        {
                                            matched = false;
                                            if (debug)
                                            {
                                                System.err.println("no matched 2 for token: '" + tok + "'");
                                            }
                                        }
                                    }
                                    escaped = false;
                                    break;
                                }
                            }
                        }
                    }
                    else if (tok.equals("_") && (!escaped))
                    {
                        index++;
                        if (debug)
                        {
                            System.err.println("matched2: " + str.substring(0, index));
                        }
                    }
                    else
                    {
                        // Compare token read with corresponding string
                        int tokLen = tok.length();

                        if (debug)
                        {
                            System.err.println(index + " " + tokLen);
                        }
                        if (index + tokLen <= str.length())
                        {
                            String subStr = null;

                            try
                            {
                                subStr = str.substring(index, index + tokLen);
                            }
                            catch (StringIndexOutOfBoundsException e)
                            {
                                matched = false;
                                break;
                            }

                            if (!subStr.equalsIgnoreCase(tok))
                            {
                                matched = false;
                                if (debug)
                                {
                                    System.err.println("no matched3 for token: '" + tok + "'");
                                }

                                break;
                            }
                            else
                            {
                                index = index + tok.length();
                                if (debug)
                                {
                                    System.err.println("matched3: " + str.substring(0, index));
                                }
                            }
                        }
                        else
                        {
                            matched = false;
                            if (debug)
                            {
                                System.err.println("no matched4 for token: '" + tok + "'");
                            }

                            break;
                        }
                        escaped = false;
                    }
                }
            }
            if (matched && index != str.length())
            {
                if (debug)
                {
                    System.err.println("no match5(remainder): " + str.substring(index, str.length()));
                }
                matched = false;
            }
            if (debug)
            {
                System.err.println("JMSSelector:matchPattern patternStr = \'" + patternStr + "\' str = \'" + str + "\' matched = " + matched);
            }
        }
        catch (StringIndexOutOfBoundsException e)
        {
            matched = false;
            if (debug)
            {
                e.printStackTrace();
                System.err.println("HANDLED OUTOFBOUNDS JMSSelector:matchPattern patternStr = \'" + patternStr + "\' str = \'" + str + "\' matched = " + matched);

            }
        }

        return matched;
    }

    /**
     * Strip leading and trailing quotes from a String Literal.
     * Also, the nested quote character is represented as 2
     * consecutive quotes, so replace all occurrances of double
     * quotes with single quotes.
     */
    String processStringLiteral(String strLiteral) {

    //Strip leading and trailing quotes
    strLiteral = strLiteral.substring(1, strLiteral.length()-1);

        // Replace all occurances of consecutive quotes as single quote.
        int index = strLiteral.indexOf("''");
        if (index > -1) {
            StringBuffer sb = new StringBuffer(strLiteral);
            while (index != -1) {
                sb.deleteCharAt(index);
                index = sb.toString().indexOf("''");
            }
            strLiteral = sb.toString();
        }
        return strLiteral;
    }
}
TOP

Related Classes of flex.messaging.services.messaging.selector.JMSSelector

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.