You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by yu...@apache.org on 2017/08/01 07:23:22 UTC

[24/50] [abbrv] incubator-rocketmq git commit: [ROCKETMQ-121]Support message filtering based on SQL92 closes apache/incubator-rocketmq#82

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java
new file mode 100644
index 0000000..915658c
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+/* Generated By:JavaCC: Do not edit this line. SelectorParserConstants.java */
+package org.apache.rocketmq.filter.parser;
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface SelectorParserConstants {
+
+    /**
+     * End of File.
+     */
+    int EOF = 0;
+    /**
+     * RegularExpression Id.
+     */
+    int LINE_COMMENT = 6;
+    /**
+     * RegularExpression Id.
+     */
+    int BLOCK_COMMENT = 7;
+    /**
+     * RegularExpression Id.
+     */
+    int NOT = 8;
+    /**
+     * RegularExpression Id.
+     */
+    int AND = 9;
+    /**
+     * RegularExpression Id.
+     */
+    int OR = 10;
+    /**
+     * RegularExpression Id.
+     */
+    int BETWEEN = 11;
+    /**
+     * RegularExpression Id.
+     */
+    int IN = 12;
+    /**
+     * RegularExpression Id.
+     */
+    int TRUE = 13;
+    /**
+     * RegularExpression Id.
+     */
+    int FALSE = 14;
+    /**
+     * RegularExpression Id.
+     */
+    int NULL = 15;
+    /**
+     * RegularExpression Id.
+     */
+    int IS = 16;
+    /**
+     * RegularExpression Id.
+     */
+    int DECIMAL_LITERAL = 17;
+    /**
+     * RegularExpression Id.
+     */
+    int FLOATING_POINT_LITERAL = 18;
+    /**
+     * RegularExpression Id.
+     */
+    int EXPONENT = 19;
+    /**
+     * RegularExpression Id.
+     */
+    int STRING_LITERAL = 20;
+    /**
+     * RegularExpression Id.
+     */
+    int ID = 21;
+
+    /**
+     * Lexical state.
+     */
+    int DEFAULT = 0;
+
+    /**
+     * Literal token values.
+     */
+    String[] TOKEN_IMAGE = {
+        "<EOF>",
+        "\" \"",
+        "\"\\t\"",
+        "\"\\n\"",
+        "\"\\r\"",
+        "\"\\f\"",
+        "<LINE_COMMENT>",
+        "<BLOCK_COMMENT>",
+        "\"NOT\"",
+        "\"AND\"",
+        "\"OR\"",
+        "\"BETWEEN\"",
+        "\"IN\"",
+        "\"TRUE\"",
+        "\"FALSE\"",
+        "\"NULL\"",
+        "\"IS\"",
+        "<DECIMAL_LITERAL>",
+        "<FLOATING_POINT_LITERAL>",
+        "<EXPONENT>",
+        "<STRING_LITERAL>",
+        "<ID>",
+        "\"=\"",
+        "\"<>\"",
+        "\">\"",
+        "\">=\"",
+        "\"<\"",
+        "\"<=\"",
+        "\"(\"",
+        "\",\"",
+        "\")\"",
+        "\"+\"",
+        "\"-\"",
+    };
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java
new file mode 100644
index 0000000..354f5ba
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java
@@ -0,0 +1,919 @@
+/*
+ * 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.
+ */
+
+/* Generated By:JavaCC: Do not edit this line. SelectorParserTokenManager.java */
+package org.apache.rocketmq.filter.parser;
+
+/**
+ * Token Manager.
+ */
+public class SelectorParserTokenManager implements SelectorParserConstants {
+
+    /**
+     * Debug output.
+     */
+    public java.io.PrintStream debugStream = System.out;
+
+    /**
+     * Set debug output.
+     */
+    public void setDebugStream(java.io.PrintStream ds) {
+        debugStream = ds;
+    }
+
+    private int jjStopAtPos(int pos, int kind) {
+        jjmatchedKind = kind;
+        jjmatchedPos = pos;
+        return pos + 1;
+    }
+
+    private int jjMoveStringLiteralDfa0_0() {
+        switch (curChar) {
+            case 9:
+                jjmatchedKind = 2;
+                return jjMoveNfa_0(5, 0);
+            case 10:
+                jjmatchedKind = 3;
+                return jjMoveNfa_0(5, 0);
+            case 12:
+                jjmatchedKind = 5;
+                return jjMoveNfa_0(5, 0);
+            case 13:
+                jjmatchedKind = 4;
+                return jjMoveNfa_0(5, 0);
+            case 32:
+                jjmatchedKind = 1;
+                return jjMoveNfa_0(5, 0);
+            case 40:
+                jjmatchedKind = 28;
+                return jjMoveNfa_0(5, 0);
+            case 41:
+                jjmatchedKind = 30;
+                return jjMoveNfa_0(5, 0);
+            case 43:
+                jjmatchedKind = 31;
+                return jjMoveNfa_0(5, 0);
+            case 44:
+                jjmatchedKind = 29;
+                return jjMoveNfa_0(5, 0);
+            case 45:
+                jjmatchedKind = 32;
+                return jjMoveNfa_0(5, 0);
+            case 60:
+                jjmatchedKind = 26;
+                return jjMoveStringLiteralDfa1_0(0x8800000L);
+            case 61:
+                jjmatchedKind = 22;
+                return jjMoveNfa_0(5, 0);
+            case 62:
+                jjmatchedKind = 24;
+                return jjMoveStringLiteralDfa1_0(0x2000000L);
+            case 65:
+                return jjMoveStringLiteralDfa1_0(0x200L);
+            case 66:
+                return jjMoveStringLiteralDfa1_0(0x800L);
+            case 70:
+                return jjMoveStringLiteralDfa1_0(0x4000L);
+            case 73:
+                return jjMoveStringLiteralDfa1_0(0x11000L);
+            case 78:
+                return jjMoveStringLiteralDfa1_0(0x8100L);
+            case 79:
+                return jjMoveStringLiteralDfa1_0(0x400L);
+            case 84:
+                return jjMoveStringLiteralDfa1_0(0x2000L);
+            case 97:
+                return jjMoveStringLiteralDfa1_0(0x200L);
+            case 98:
+                return jjMoveStringLiteralDfa1_0(0x800L);
+            case 102:
+                return jjMoveStringLiteralDfa1_0(0x4000L);
+            case 105:
+                return jjMoveStringLiteralDfa1_0(0x11000L);
+            case 110:
+                return jjMoveStringLiteralDfa1_0(0x8100L);
+            case 111:
+                return jjMoveStringLiteralDfa1_0(0x400L);
+            case 116:
+                return jjMoveStringLiteralDfa1_0(0x2000L);
+            default:
+                return jjMoveNfa_0(5, 0);
+        }
+    }
+
+    private int jjMoveStringLiteralDfa1_0(long active0) {
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 0);
+        }
+        switch (curChar) {
+            case 61:
+                if ((active0 & 0x2000000L) != 0L) {
+                    jjmatchedKind = 25;
+                    jjmatchedPos = 1;
+                } else if ((active0 & 0x8000000L) != 0L) {
+                    jjmatchedKind = 27;
+                    jjmatchedPos = 1;
+                }
+                break;
+            case 62:
+                if ((active0 & 0x800000L) != 0L) {
+                    jjmatchedKind = 23;
+                    jjmatchedPos = 1;
+                }
+                break;
+            case 65:
+                return jjMoveStringLiteralDfa2_0(active0, 0x4000L);
+            case 69:
+                return jjMoveStringLiteralDfa2_0(active0, 0x800L);
+            case 78:
+                if ((active0 & 0x1000L) != 0L) {
+                    jjmatchedKind = 12;
+                    jjmatchedPos = 1;
+                }
+                return jjMoveStringLiteralDfa2_0(active0, 0x200L);
+            case 79:
+                return jjMoveStringLiteralDfa2_0(active0, 0x100L);
+            case 82:
+                if ((active0 & 0x400L) != 0L) {
+                    jjmatchedKind = 10;
+                    jjmatchedPos = 1;
+                }
+                return jjMoveStringLiteralDfa2_0(active0, 0x2000L);
+            case 83:
+                if ((active0 & 0x10000L) != 0L) {
+                    jjmatchedKind = 16;
+                    jjmatchedPos = 1;
+                }
+                break;
+            case 85:
+                return jjMoveStringLiteralDfa2_0(active0, 0x8000L);
+            case 97:
+                return jjMoveStringLiteralDfa2_0(active0, 0x4000L);
+            case 101:
+                return jjMoveStringLiteralDfa2_0(active0, 0x800L);
+            case 110:
+                if ((active0 & 0x1000L) != 0L) {
+                    jjmatchedKind = 12;
+                    jjmatchedPos = 1;
+                }
+                return jjMoveStringLiteralDfa2_0(active0, 0x200L);
+            case 111:
+                return jjMoveStringLiteralDfa2_0(active0, 0x100L);
+            case 114:
+                if ((active0 & 0x400L) != 0L) {
+                    jjmatchedKind = 10;
+                    jjmatchedPos = 1;
+                }
+                return jjMoveStringLiteralDfa2_0(active0, 0x2000L);
+            case 115:
+                if ((active0 & 0x10000L) != 0L) {
+                    jjmatchedKind = 16;
+                    jjmatchedPos = 1;
+                }
+                break;
+            case 117:
+                return jjMoveStringLiteralDfa2_0(active0, 0x8000L);
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 1);
+    }
+
+    private int jjMoveStringLiteralDfa2_0(long old0, long active0) {
+        if (((active0 &= old0)) == 0L)
+            return jjMoveNfa_0(5, 1);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 1);
+        }
+        switch (curChar) {
+            case 68:
+                if ((active0 & 0x200L) != 0L) {
+                    jjmatchedKind = 9;
+                    jjmatchedPos = 2;
+                }
+                break;
+            case 76:
+                return jjMoveStringLiteralDfa3_0(active0, 0xc000L);
+            case 84:
+                if ((active0 & 0x100L) != 0L) {
+                    jjmatchedKind = 8;
+                    jjmatchedPos = 2;
+                }
+                return jjMoveStringLiteralDfa3_0(active0, 0x800L);
+            case 85:
+                return jjMoveStringLiteralDfa3_0(active0, 0x2000L);
+            case 100:
+                if ((active0 & 0x200L) != 0L) {
+                    jjmatchedKind = 9;
+                    jjmatchedPos = 2;
+                }
+                break;
+            case 108:
+                return jjMoveStringLiteralDfa3_0(active0, 0xc000L);
+            case 116:
+                if ((active0 & 0x100L) != 0L) {
+                    jjmatchedKind = 8;
+                    jjmatchedPos = 2;
+                }
+                return jjMoveStringLiteralDfa3_0(active0, 0x800L);
+            case 117:
+                return jjMoveStringLiteralDfa3_0(active0, 0x2000L);
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 2);
+    }
+
+    private int jjMoveStringLiteralDfa3_0(long old0, long active0) {
+        if (((active0 &= old0)) == 0L)
+            return jjMoveNfa_0(5, 2);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 2);
+        }
+        switch (curChar) {
+            case 69:
+                if ((active0 & 0x2000L) != 0L) {
+                    jjmatchedKind = 13;
+                    jjmatchedPos = 3;
+                }
+                break;
+            case 76:
+                if ((active0 & 0x8000L) != 0L) {
+                    jjmatchedKind = 15;
+                    jjmatchedPos = 3;
+                }
+                break;
+            case 83:
+                return jjMoveStringLiteralDfa4_0(active0, 0x4000L);
+            case 87:
+                return jjMoveStringLiteralDfa4_0(active0, 0x800L);
+            case 101:
+                if ((active0 & 0x2000L) != 0L) {
+                    jjmatchedKind = 13;
+                    jjmatchedPos = 3;
+                }
+                break;
+            case 108:
+                if ((active0 & 0x8000L) != 0L) {
+                    jjmatchedKind = 15;
+                    jjmatchedPos = 3;
+                }
+                break;
+            case 115:
+                return jjMoveStringLiteralDfa4_0(active0, 0x4000L);
+            case 119:
+                return jjMoveStringLiteralDfa4_0(active0, 0x800L);
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 3);
+    }
+
+    private int jjMoveStringLiteralDfa4_0(long old0, long active0) {
+        if (((active0 &= old0)) == 0L)
+            return jjMoveNfa_0(5, 3);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 3);
+        }
+        switch (curChar) {
+            case 69:
+                if ((active0 & 0x4000L) != 0L) {
+                    jjmatchedKind = 14;
+                    jjmatchedPos = 4;
+                }
+                return jjMoveStringLiteralDfa5_0(active0, 0x800L);
+            case 101:
+                if ((active0 & 0x4000L) != 0L) {
+                    jjmatchedKind = 14;
+                    jjmatchedPos = 4;
+                }
+                return jjMoveStringLiteralDfa5_0(active0, 0x800L);
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 4);
+    }
+
+    private int jjMoveStringLiteralDfa5_0(long old0, long active0) {
+        if (((active0 &= old0)) == 0L)
+            return jjMoveNfa_0(5, 4);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 4);
+        }
+        switch (curChar) {
+            case 69:
+                return jjMoveStringLiteralDfa6_0(active0, 0x800L);
+            case 101:
+                return jjMoveStringLiteralDfa6_0(active0, 0x800L);
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 5);
+    }
+
+    private int jjMoveStringLiteralDfa6_0(long old0, long active0) {
+        if (((active0 &= old0)) == 0L)
+            return jjMoveNfa_0(5, 5);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            return jjMoveNfa_0(5, 5);
+        }
+        switch (curChar) {
+            case 78:
+                if ((active0 & 0x800L) != 0L) {
+                    jjmatchedKind = 11;
+                    jjmatchedPos = 6;
+                }
+                break;
+            case 110:
+                if ((active0 & 0x800L) != 0L) {
+                    jjmatchedKind = 11;
+                    jjmatchedPos = 6;
+                }
+                break;
+            default:
+                break;
+        }
+        return jjMoveNfa_0(5, 6);
+    }
+
+    static final long[] JJ_BIT_VEC_0 = {
+        0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+    };
+    static final long[] JJ_BIT_VEC_2 = {
+        0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+    };
+
+    private int jjMoveNfa_0(int startState, int curPos) {
+        int strKind = jjmatchedKind;
+        int strPos = jjmatchedPos;
+        int seenUpto;
+        inputStream.backup(seenUpto = curPos + 1);
+        try {
+            curChar = inputStream.readChar();
+        } catch (java.io.IOException e) {
+            throw new Error("Internal Error");
+        }
+        curPos = 0;
+        int startsAt = 0;
+        jjnewStateCnt = 40;
+        int i = 1;
+        jjstateSet[0] = startState;
+        int kind = 0x7fffffff;
+        for (;;) {
+            if (++jjround == 0x7fffffff)
+                ReInitRounds();
+            if (curChar < 64) {
+                long l = 1L << curChar;
+                do {
+                    switch (jjstateSet[--i]) {
+                        case 5:
+                            if ((0x3ff000000000000L & l) != 0L)
+                                jjCheckNAddStates(0, 3);
+                            else if (curChar == 36) {
+                                if (kind > 21)
+                                    kind = 21;
+                                jjCheckNAdd(28);
+                            } else if (curChar == 39)
+                                jjCheckNAddStates(4, 6);
+                            else if (curChar == 46)
+                                jjCheckNAdd(18);
+                            else if (curChar == 47)
+                                jjstateSet[jjnewStateCnt++] = 6;
+                            else if (curChar == 45)
+                                jjstateSet[jjnewStateCnt++] = 0;
+                            if ((0x3fe000000000000L & l) != 0L) {
+                                if (kind > 17)
+                                    kind = 17;
+                                jjCheckNAddTwoStates(15, 16);
+                            } else if (curChar == 48) {
+                                if (kind > 17)
+                                    kind = 17;
+                            }
+                            break;
+                        case 0:
+                            if (curChar == 45)
+                                jjCheckNAddStates(7, 9);
+                            break;
+                        case 1:
+                            if ((0xffffffffffffdbffL & l) != 0L)
+                                jjCheckNAddStates(7, 9);
+                            break;
+                        case 2:
+                            if ((0x2400L & l) != 0L && kind > 6)
+                                kind = 6;
+                            break;
+                        case 3:
+                            if (curChar == 10 && kind > 6)
+                                kind = 6;
+                            break;
+                        case 4:
+                            if (curChar == 13)
+                                jjstateSet[jjnewStateCnt++] = 3;
+                            break;
+                        case 6:
+                            if (curChar == 42)
+                                jjCheckNAddTwoStates(7, 8);
+                            break;
+                        case 7:
+                            if ((0xfffffbffffffffffL & l) != 0L)
+                                jjCheckNAddTwoStates(7, 8);
+                            break;
+                        case 8:
+                            if (curChar == 42)
+                                jjCheckNAddStates(10, 12);
+                            break;
+                        case 9:
+                            if ((0xffff7bffffffffffL & l) != 0L)
+                                jjCheckNAddTwoStates(10, 8);
+                            break;
+                        case 10:
+                            if ((0xfffffbffffffffffL & l) != 0L)
+                                jjCheckNAddTwoStates(10, 8);
+                            break;
+                        case 11:
+                            if (curChar == 47 && kind > 7)
+                                kind = 7;
+                            break;
+                        case 12:
+                            if (curChar == 47)
+                                jjstateSet[jjnewStateCnt++] = 6;
+                            break;
+                        case 13:
+                            if (curChar == 48 && kind > 17)
+                                kind = 17;
+                            break;
+                        case 14:
+                            if ((0x3fe000000000000L & l) == 0L)
+                                break;
+                            if (kind > 17)
+                                kind = 17;
+                            jjCheckNAddTwoStates(15, 16);
+                            break;
+                        case 15:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 17)
+                                kind = 17;
+                            jjCheckNAddTwoStates(15, 16);
+                            break;
+                        case 17:
+                            if (curChar == 46)
+                                jjCheckNAdd(18);
+                            break;
+                        case 18:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAddTwoStates(18, 19);
+                            break;
+                        case 20:
+                            if ((0x280000000000L & l) != 0L)
+                                jjCheckNAdd(21);
+                            break;
+                        case 21:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAdd(21);
+                            break;
+                        case 22:
+                        case 23:
+                            if (curChar == 39)
+                                jjCheckNAddStates(4, 6);
+                            break;
+                        case 24:
+                            if (curChar == 39)
+                                jjstateSet[jjnewStateCnt++] = 23;
+                            break;
+                        case 25:
+                            if ((0xffffff7fffffffffL & l) != 0L)
+                                jjCheckNAddStates(4, 6);
+                            break;
+                        case 26:
+                            if (curChar == 39 && kind > 20)
+                                kind = 20;
+                            break;
+                        case 27:
+                            if (curChar != 36)
+                                break;
+                            if (kind > 21)
+                                kind = 21;
+                            jjCheckNAdd(28);
+                            break;
+                        case 28:
+                            if ((0x3ff001000000000L & l) == 0L)
+                                break;
+                            if (kind > 21)
+                                kind = 21;
+                            jjCheckNAdd(28);
+                            break;
+                        case 29:
+                            if ((0x3ff000000000000L & l) != 0L)
+                                jjCheckNAddStates(0, 3);
+                            break;
+                        case 30:
+                            if ((0x3ff000000000000L & l) != 0L)
+                                jjCheckNAddTwoStates(30, 31);
+                            break;
+                        case 31:
+                            if (curChar != 46)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAddTwoStates(32, 33);
+                            break;
+                        case 32:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAddTwoStates(32, 33);
+                            break;
+                        case 34:
+                            if ((0x280000000000L & l) != 0L)
+                                jjCheckNAdd(35);
+                            break;
+                        case 35:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAdd(35);
+                            break;
+                        case 36:
+                            if ((0x3ff000000000000L & l) != 0L)
+                                jjCheckNAddTwoStates(36, 37);
+                            break;
+                        case 38:
+                            if ((0x280000000000L & l) != 0L)
+                                jjCheckNAdd(39);
+                            break;
+                        case 39:
+                            if ((0x3ff000000000000L & l) == 0L)
+                                break;
+                            if (kind > 18)
+                                kind = 18;
+                            jjCheckNAdd(39);
+                            break;
+                        default:
+                            break;
+                    }
+                } while (i != startsAt);
+            } else if (curChar < 128) {
+                long l = 1L << (curChar & 077);
+                do {
+                    switch (jjstateSet[--i]) {
+                        case 5:
+                        case 28:
+                            if ((0x7fffffe87fffffeL & l) == 0L)
+                                break;
+                            if (kind > 21)
+                                kind = 21;
+                            jjCheckNAdd(28);
+                            break;
+                        case 1:
+                            jjAddStates(7, 9);
+                            break;
+                        case 7:
+                            jjCheckNAddTwoStates(7, 8);
+                            break;
+                        case 9:
+                        case 10:
+                            jjCheckNAddTwoStates(10, 8);
+                            break;
+                        case 16:
+                            if ((0x100000001000L & l) != 0L && kind > 17)
+                                kind = 17;
+                            break;
+                        case 19:
+                            if ((0x2000000020L & l) != 0L)
+                                jjAddStates(13, 14);
+                            break;
+                        case 25:
+                            jjAddStates(4, 6);
+                            break;
+                        case 33:
+                            if ((0x2000000020L & l) != 0L)
+                                jjAddStates(15, 16);
+                            break;
+                        case 37:
+                            if ((0x2000000020L & l) != 0L)
+                                jjAddStates(17, 18);
+                            break;
+                        default:
+                            break;
+                    }
+                } while (i != startsAt);
+            } else {
+                int hiByte = (int) (curChar >> 8);
+                int i1 = hiByte >> 6;
+                long l1 = 1L << (hiByte & 077);
+                int i2 = (curChar & 0xff) >> 6;
+                long l2 = 1L << (curChar & 077);
+                do {
+                    switch (jjstateSet[--i]) {
+                        case 1:
+                            if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                                jjAddStates(7, 9);
+                            break;
+                        case 7:
+                            if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                                jjCheckNAddTwoStates(7, 8);
+                            break;
+                        case 9:
+                        case 10:
+                            if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                                jjCheckNAddTwoStates(10, 8);
+                            break;
+                        case 25:
+                            if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                                jjAddStates(4, 6);
+                            break;
+                        default:
+                            break;
+                    }
+                } while (i != startsAt);
+            }
+            if (kind != 0x7fffffff) {
+                jjmatchedKind = kind;
+                jjmatchedPos = curPos;
+                kind = 0x7fffffff;
+            }
+            ++curPos;
+            if ((i = jjnewStateCnt) == (startsAt = 40 - (jjnewStateCnt = startsAt)))
+                break;
+            try {
+                curChar = inputStream.readChar();
+            } catch (java.io.IOException e) {
+                break;
+            }
+        }
+        if (jjmatchedPos > strPos)
+            return curPos;
+
+        int toRet = Math.max(curPos, seenUpto);
+
+        if (curPos < toRet)
+            for (i = toRet - Math.min(curPos, seenUpto); i-- > 0; )
+                try {
+                    curChar = inputStream.readChar();
+                } catch (java.io.IOException e) {
+                    throw new Error("Internal Error : Please send a bug report.");
+                }
+
+        if (jjmatchedPos < strPos) {
+            jjmatchedKind = strKind;
+            jjmatchedPos = strPos;
+        } else if (jjmatchedPos == strPos && jjmatchedKind > strKind)
+            jjmatchedKind = strKind;
+
+        return toRet;
+    }
+
+    static final int[] JJ_NEXT_STATES = {
+        30, 31, 36, 37, 24, 25, 26, 1, 2, 4, 8, 9, 11, 20, 21, 34,
+        35, 38, 39,
+    };
+
+    private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) {
+        switch (hiByte) {
+            case 0:
+                return (JJ_BIT_VEC_2[i2] & l2) != 0L;
+            default:
+                if ((JJ_BIT_VEC_0[i1] & l1) != 0L)
+                    return true;
+                return false;
+        }
+    }
+
+    /**
+     * Token literal values.
+     */
+    public static final String[] JJ_STR_LITERAL_IMAGES = {
+        "", null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, "\75", "\74\76", "\76",
+        "\76\75", "\74", "\74\75", "\50", "\54", "\51", "\53", "\55"};
+
+    /**
+     * Lexer state names.
+     */
+    public static final String[] LEX_STATE_NAMES = {
+        "DEFAULT",
+    };
+    static final long[] JJ_TO_TOKEN = {
+        0x1fff7ff01L,
+    };
+    static final long[] JJ_TO_SKIP = {
+        0xfeL,
+    };
+    static final long[] JJ_TO_SPECIAL = {
+        0x3eL,
+    };
+    protected SimpleCharStream inputStream;
+    private final int[] jjrounds = new int[40];
+    private final int[] jjstateSet = new int[80];
+    protected char curChar;
+
+    /**
+     * Constructor.
+     */
+    public SelectorParserTokenManager(SimpleCharStream stream) {
+        if (SimpleCharStream.STATIC_FLAG)
+            throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+        inputStream = stream;
+    }
+
+    /**
+     * Constructor.
+     */
+    public SelectorParserTokenManager(SimpleCharStream stream, int lexState) {
+        this(stream);
+        SwitchTo(lexState);
+    }
+
+    /**
+     * Reinitialise parser.
+     */
+    public void ReInit(SimpleCharStream stream) {
+        jjmatchedPos = jjnewStateCnt = 0;
+        curLexState = defaultLexState;
+        inputStream = stream;
+        ReInitRounds();
+    }
+
+    private void ReInitRounds() {
+        int i;
+        jjround = 0x80000001;
+        for (i = 40; i-- > 0; )
+            jjrounds[i] = 0x80000000;
+    }
+
+    /**
+     * Reinitialise parser.
+     */
+    public void ReInit(SimpleCharStream stream, int lexState) {
+        ReInit(stream);
+        SwitchTo(lexState);
+    }
+
+    /**
+     * Switch to specified lex state.
+     */
+    public void SwitchTo(int lexState) {
+        if (lexState >= 1 || lexState < 0)
+            throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.",
+                TokenMgrError.INVALID_LEXICAL_STATE);
+        else
+            curLexState = lexState;
+    }
+
+    protected Token jjFillToken() {
+        final Token t;
+        final String curTokenImage;
+        final int beginLine;
+        final int endLine;
+        final int beginColumn;
+        final int endColumn;
+        String im = JJ_STR_LITERAL_IMAGES[jjmatchedKind];
+        curTokenImage = (im == null) ? inputStream.GetImage() : im;
+        beginLine = inputStream.getBeginLine();
+        beginColumn = inputStream.getBeginColumn();
+        endLine = inputStream.getEndLine();
+        endColumn = inputStream.getEndColumn();
+        t = Token.newToken(jjmatchedKind, curTokenImage);
+
+        t.beginLine = beginLine;
+        t.endLine = endLine;
+        t.beginColumn = beginColumn;
+        t.endColumn = endColumn;
+
+        return t;
+    }
+
+    int curLexState = 0;
+    int defaultLexState = 0;
+    int jjnewStateCnt;
+    int jjround;
+    int jjmatchedPos;
+    int jjmatchedKind;
+
+    /**
+     * Get the next Token.
+     */
+    public Token getNextToken() {
+        Token specialToken = null;
+        Token matchedToken;
+        int curPos = 0;
+
+        EOFLoop:
+        for (;;) {
+            try {
+                curChar = inputStream.BeginToken();
+            } catch (java.io.IOException e) {
+                jjmatchedKind = 0;
+                matchedToken = jjFillToken();
+                matchedToken.specialToken = specialToken;
+                return matchedToken;
+            }
+
+            jjmatchedKind = 0x7fffffff;
+            jjmatchedPos = 0;
+            curPos = jjMoveStringLiteralDfa0_0();
+            if (jjmatchedKind != 0x7fffffff) {
+                if (jjmatchedPos + 1 < curPos)
+                    inputStream.backup(curPos - jjmatchedPos - 1);
+                if ((JJ_TO_TOKEN[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) {
+                    matchedToken = jjFillToken();
+                    matchedToken.specialToken = specialToken;
+                    return matchedToken;
+                } else {
+                    if ((JJ_TO_SPECIAL[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) {
+                        matchedToken = jjFillToken();
+                        if (specialToken == null)
+                            specialToken = matchedToken;
+                        else {
+                            matchedToken.specialToken = specialToken;
+                            specialToken = specialToken.next = matchedToken;
+                        }
+                    }
+                    continue EOFLoop;
+                }
+            }
+            int errorLine = inputStream.getEndLine();
+            int errorColumn = inputStream.getEndColumn();
+            String errorAfter = null;
+            boolean eofSeen = false;
+            try {
+                inputStream.readChar();
+                inputStream.backup(1);
+            } catch (java.io.IOException e1) {
+                eofSeen = true;
+                errorAfter = curPos <= 1 ? "" : inputStream.GetImage();
+                if (curChar == '\n' || curChar == '\r') {
+                    errorLine++;
+                    errorColumn = 0;
+                } else
+                    errorColumn++;
+            }
+            if (!eofSeen) {
+                inputStream.backup(1);
+                errorAfter = curPos <= 1 ? "" : inputStream.GetImage();
+            }
+            throw new TokenMgrError(eofSeen, curLexState, errorLine, errorColumn, errorAfter, curChar,
+                TokenMgrError.LEXICAL_ERROR);
+        }
+    }
+
+    private void jjCheckNAdd(int state) {
+        if (jjrounds[state] != jjround) {
+            jjstateSet[jjnewStateCnt++] = state;
+            jjrounds[state] = jjround;
+        }
+    }
+
+    private void jjAddStates(int start, int end) {
+        do {
+            jjstateSet[jjnewStateCnt++] = JJ_NEXT_STATES[start];
+        } while (start++ != end);
+    }
+
+    private void jjCheckNAddTwoStates(int state1, int state2) {
+        jjCheckNAdd(state1);
+        jjCheckNAdd(state2);
+    }
+
+    private void jjCheckNAddStates(int start, int end) {
+        do {
+            jjCheckNAdd(JJ_NEXT_STATES[start]);
+        } while (start++ != end);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
new file mode 100644
index 0000000..94a54b4
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java
@@ -0,0 +1,502 @@
+/*
+ * 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.
+ */
+
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.rocketmq.filter.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream {
+    /**
+     * Whether parser is static.
+     */
+    public static final boolean STATIC_FLAG = false;
+    int bufsize;
+    int available;
+    int tokenBegin;
+    /**
+     * Position in buffer.
+     */
+    public int bufpos = -1;
+    protected int bufline[];
+    protected int bufcolumn[];
+
+    protected int column = 0;
+    protected int line = 1;
+
+    protected boolean prevCharIsCR = false;
+    protected boolean prevCharIsLF = false;
+
+    protected java.io.Reader inputStream;
+
+    protected char[] buffer;
+    protected int maxNextCharInd = 0;
+    protected int inBuf = 0;
+    protected int tabSize = 8;
+
+    protected void setTabSize(int i) {
+        tabSize = i;
+    }
+
+    protected int getTabSize(int i) {
+        return tabSize;
+    }
+
+    protected void ExpandBuff(boolean wrapAround) {
+        char[] newbuffer = new char[bufsize + 2048];
+        int newbufline[] = new int[bufsize + 2048];
+        int newbufcolumn[] = new int[bufsize + 2048];
+
+        try {
+            if (wrapAround) {
+                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+                System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+                buffer = newbuffer;
+
+                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+                System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+                bufline = newbufline;
+
+                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+                System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+                bufcolumn = newbufcolumn;
+
+                maxNextCharInd = bufpos += bufsize - tokenBegin;
+            } else {
+                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+                buffer = newbuffer;
+
+                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+                bufline = newbufline;
+
+                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+                bufcolumn = newbufcolumn;
+
+                maxNextCharInd = bufpos -= tokenBegin;
+            }
+        } catch (Throwable t) {
+            throw new Error(t.getMessage());
+        }
+
+        bufsize += 2048;
+        available = bufsize;
+        tokenBegin = 0;
+    }
+
+    protected void FillBuff() throws java.io.IOException {
+        if (maxNextCharInd == available) {
+            if (available == bufsize) {
+                if (tokenBegin > 2048) {
+                    bufpos = maxNextCharInd = 0;
+                    available = tokenBegin;
+                } else if (tokenBegin < 0)
+                    bufpos = maxNextCharInd = 0;
+                else
+                    ExpandBuff(false);
+            } else if (available > tokenBegin)
+                available = bufsize;
+            else if ((tokenBegin - available) < 2048)
+                ExpandBuff(true);
+            else
+                available = tokenBegin;
+        }
+
+        int i;
+        try {
+            if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) {
+                inputStream.close();
+                throw new java.io.IOException();
+            } else
+                maxNextCharInd += i;
+            return;
+        } catch (java.io.IOException e) {
+            --bufpos;
+            backup(0);
+            if (tokenBegin == -1)
+                tokenBegin = bufpos;
+            throw e;
+        }
+    }
+
+    /**
+     * Start.
+     */
+    public char BeginToken() throws java.io.IOException {
+        tokenBegin = -1;
+        char c = readChar();
+        tokenBegin = bufpos;
+
+        return c;
+    }
+
+    protected void UpdateLineColumn(char c) {
+        column++;
+
+        if (prevCharIsLF) {
+            prevCharIsLF = false;
+            line += column = 1;
+        } else if (prevCharIsCR) {
+            prevCharIsCR = false;
+            if (c == '\n') {
+                prevCharIsLF = true;
+            } else
+                line += column = 1;
+        }
+
+        switch (c) {
+            case '\r':
+                prevCharIsCR = true;
+                break;
+            case '\n':
+                prevCharIsLF = true;
+                break;
+            case '\t':
+                column--;
+                column += tabSize - (column % tabSize);
+                break;
+            default:
+                break;
+        }
+
+        bufline[bufpos] = line;
+        bufcolumn[bufpos] = column;
+    }
+
+    /**
+     * Read a character.
+     */
+    public char readChar() throws java.io.IOException {
+        if (inBuf > 0) {
+            --inBuf;
+
+            if (++bufpos == bufsize)
+                bufpos = 0;
+
+            return buffer[bufpos];
+        }
+
+        if (++bufpos >= maxNextCharInd)
+            FillBuff();
+
+        char c = buffer[bufpos];
+
+        UpdateLineColumn(c);
+        return c;
+    }
+
+    @Deprecated
+    /**
+     * @deprecated
+     * @see #getEndColumn
+     */
+
+    public int getColumn() {
+        return bufcolumn[bufpos];
+    }
+
+    @Deprecated
+    /**
+     * @deprecated
+     * @see #getEndLine
+     */
+
+    public int getLine() {
+        return bufline[bufpos];
+    }
+
+    /**
+     * Get token end column number.
+     */
+    public int getEndColumn() {
+        return bufcolumn[bufpos];
+    }
+
+    /**
+     * Get token end line number.
+     */
+    public int getEndLine() {
+        return bufline[bufpos];
+    }
+
+    /**
+     * Get token beginning column number.
+     */
+    public int getBeginColumn() {
+        return bufcolumn[tokenBegin];
+    }
+
+    /**
+     * Get token beginning line number.
+     */
+    public int getBeginLine() {
+        return bufline[tokenBegin];
+    }
+
+    /**
+     * Backup a number of characters.
+     */
+    public void backup(int amount) {
+
+        inBuf += amount;
+        if ((bufpos -= amount) < 0)
+            bufpos += bufsize;
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.Reader dstream, int startline,
+                            int startcolumn, int buffersize) {
+        inputStream = dstream;
+        line = startline;
+        column = startcolumn - 1;
+
+        available = bufsize = buffersize;
+        buffer = new char[buffersize];
+        bufline = new int[buffersize];
+        bufcolumn = new int[buffersize];
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.Reader dstream, int startline,
+                            int startcolumn) {
+        this(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.Reader dstream) {
+        this(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream, int startline,
+                       int startcolumn, int buffersize) {
+        inputStream = dstream;
+        line = startline;
+        column = startcolumn - 1;
+
+        if (buffer == null || buffersize != buffer.length) {
+            available = bufsize = buffersize;
+            buffer = new char[buffersize];
+            bufline = new int[buffersize];
+            bufcolumn = new int[buffersize];
+        }
+        prevCharIsLF = prevCharIsCR = false;
+        tokenBegin = inBuf = maxNextCharInd = 0;
+        bufpos = -1;
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream, int startline,
+                       int startcolumn) {
+        ReInit(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream) {
+        ReInit(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                            int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
+        this(encoding == null ?
+            new java.io.InputStreamReader(dstream) :
+            new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream, int startline,
+                            int startcolumn, int buffersize) {
+        this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                            int startcolumn) throws java.io.UnsupportedEncodingException {
+        this(dstream, encoding, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream, int startline,
+                            int startcolumn) {
+        this(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
+        this(dstream, encoding, 1, 1, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public SimpleCharStream(java.io.InputStream dstream) {
+        this(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                       int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
+        ReInit(encoding == null ?
+            new java.io.InputStreamReader(dstream) :
+            new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, int startline,
+                       int startcolumn, int buffersize) {
+        ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream) {
+        ReInit(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                       int startcolumn) throws java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, int startline,
+                       int startcolumn) {
+        ReInit(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Get token literal value.
+     */
+    public String GetImage() {
+        if (bufpos >= tokenBegin)
+            return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+        else
+            return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                new String(buffer, 0, bufpos + 1);
+    }
+
+    /**
+     * Get the suffix.
+     */
+    public char[] GetSuffix(int len) {
+        char[] ret = new char[len];
+
+        if ((bufpos + 1) >= len)
+            System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+        else {
+            System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                len - bufpos - 1);
+            System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Reset buffer when finished.
+     */
+    public void Done() {
+        buffer = null;
+        bufline = null;
+        bufcolumn = null;
+    }
+
+    /**
+     * Method to adjust line and column numbers for the start of a token.
+     */
+    public void adjustBeginLineColumn(int newLine, int newCol) {
+        int start = tokenBegin;
+        int len;
+
+        if (bufpos >= tokenBegin) {
+            len = bufpos - tokenBegin + inBuf + 1;
+        } else {
+            len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+        }
+
+        int i = 0, j = 0, k = 0;
+        int nextColDiff = 0, columnDiff = 0;
+
+        while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) {
+            bufline[j] = newLine;
+            nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+            bufcolumn[j] = newCol + columnDiff;
+            columnDiff = nextColDiff;
+            i++;
+        }
+
+        if (i < len) {
+            bufline[j] = newLine++;
+            bufcolumn[j] = newCol + columnDiff;
+
+            while (i++ < len) {
+                if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+                    bufline[j] = newLine++;
+                else
+                    bufline[j] = newLine;
+            }
+        }
+
+        line = bufline[j];
+        column = bufcolumn[j];
+    }
+
+}
+/* JavaCC - OriginalChecksum=af79bfe4b18b4b4ea9720ffeb7e52fc5 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java
new file mode 100644
index 0000000..8e6a48a
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.rocketmq.filter.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+    /**
+     * The version identifier for this Serializable class.
+     * Increment only if the <i>serialized</i> form of the
+     * class changes.
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * An integer that describes the kind of this token.  This numbering
+     * system is determined by JavaCCParser, and a table of these numbers is
+     * stored in the file ...Constants.java.
+     */
+    public int kind;
+
+    /**
+     * The line number of the first character of this Token.
+     */
+    public int beginLine;
+    /**
+     * The column number of the first character of this Token.
+     */
+    public int beginColumn;
+    /**
+     * The line number of the last character of this Token.
+     */
+    public int endLine;
+    /**
+     * The column number of the last character of this Token.
+     */
+    public int endColumn;
+
+    /**
+     * The string image of the token.
+     */
+    public String image;
+
+    /**
+     * A reference to the next regular (non-special) token from the input
+     * stream.  If this is the last token from the input stream, or if the
+     * token manager has not read tokens beyond this one, this field is
+     * set to null.  This is true only if this token is also a regular
+     * token.  Otherwise, see below for a description of the contents of
+     * this field.
+     */
+    public Token next;
+
+    /**
+     * This field is used to access special tokens that occur prior to this
+     * token, but after the immediately preceding regular (non-special) token.
+     * If there are no such special tokens, this field is set to null.
+     * When there are more than one such special token, this field refers
+     * to the last of these special tokens, which in turn refers to the next
+     * previous special token through its specialToken field, and so on
+     * until the first special token (whose specialToken field is null).
+     * The next fields of special tokens refer to other special tokens that
+     * immediately follow it (without an intervening regular token).  If there
+     * is no such token, this field is null.
+     */
+    public Token specialToken;
+
+    /**
+     * An optional attribute value of the Token.
+     * Tokens which are not used as syntactic sugar will often contain
+     * meaningful values that will be used later on by the compiler or
+     * interpreter. This attribute value is often different from the image.
+     * Any subclass of Token that actually wants to return a non-null value can
+     * override this method as appropriate.
+     */
+    public Object getValue() {
+        return null;
+    }
+
+    /**
+     * No-argument constructor
+     */
+    public Token() {
+    }
+
+    /**
+     * Constructs a new token for the specified Image.
+     */
+    public Token(int kind) {
+        this(kind, null);
+    }
+
+    /**
+     * Constructs a new token for the specified Image and Kind.
+     */
+    public Token(int kind, String image) {
+        this.kind = kind;
+        this.image = image;
+    }
+
+    /**
+     * Returns the image.
+     */
+    public String toString() {
+        return image;
+    }
+
+    /**
+     * Returns a new Token object, by default. However, if you want, you
+     * can create and return subclass objects based on the value of ofKind.
+     * Simply add the cases to the switch for all those special cases.
+     * For example, if you have a subclass of Token called IDToken that
+     * you want to create if ofKind is ID, simply add something like :
+     * <p/>
+     * case MyParserConstants.ID : return new IDToken(ofKind, image);
+     * <p/>
+     * to the following switch statement. Then you can cast matchedToken
+     * variable to the appropriate type and use sit in your lexical actions.
+     */
+    public static Token newToken(int ofKind, String image) {
+        switch (ofKind) {
+            default:
+                return new Token(ofKind, image);
+        }
+    }
+
+    public static Token newToken(int ofKind) {
+        return newToken(ofKind, null);
+    }
+
+}
+/* JavaCC - OriginalChecksum=6b0af88eb45a551d929d3cdd9582f827 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java
new file mode 100644
index 0000000..75d83e5
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package org.apache.rocketmq.filter.parser;
+
+/**
+ * Token Manager Error.
+ */
+public class TokenMgrError extends Error {
+
+    /**
+     * The version identifier for this Serializable class.
+     * Increment only if the <i>serialized</i> form of the
+     * class changes.
+     */
+    private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+    /**
+     * Lexical error occurred.
+     */
+    static final int LEXICAL_ERROR = 0;
+
+    /**
+     * An attempt was made to create a second instance of a static token manager.
+     */
+    static final int STATIC_LEXER_ERROR = 1;
+
+    /**
+     * Tried to change to an invalid lexical state.
+     */
+    static final int INVALID_LEXICAL_STATE = 2;
+
+    /**
+     * Detected (and bailed out of) an infinite loop in the token manager.
+     */
+    static final int LOOP_DETECTED = 3;
+
+    /**
+     * Indicates the reason why the exception is thrown. It will have
+     * one of the above 4 values.
+     */
+    int errorCode;
+
+    /**
+     * Replaces unprintable characters by their escaped (or unicode escaped)
+     * equivalents in the given string
+     */
+    protected static final String addEscapes(String str) {
+        StringBuffer retval = new StringBuffer();
+        char ch;
+        for (int i = 0; i < str.length(); i++) {
+            switch (str.charAt(i)) {
+                case 0:
+                    continue;
+                case '\b':
+                    retval.append("\\b");
+                    continue;
+                case '\t':
+                    retval.append("\\t");
+                    continue;
+                case '\n':
+                    retval.append("\\n");
+                    continue;
+                case '\f':
+                    retval.append("\\f");
+                    continue;
+                case '\r':
+                    retval.append("\\r");
+                    continue;
+                case '\"':
+                    retval.append("\\\"");
+                    continue;
+                case '\'':
+                    retval.append("\\\'");
+                    continue;
+                case '\\':
+                    retval.append("\\\\");
+                    continue;
+                default:
+                    if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                        String s = "0000" + Integer.toString(ch, 16);
+                        retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+                    } else {
+                        retval.append(ch);
+                    }
+                    continue;
+            }
+        }
+        return retval.toString();
+    }
+
+    /**
+     * Returns a detailed message for the Error when it is thrown by the
+     * token manager to indicate a lexical error.
+     * Parameters :
+     * eofSeen     : indicates if EOF caused the lexical error
+     * curLexState : lexical state in which this error occurred
+     * errorLine   : line number when the error occurred
+     * errorColumn : column number when the error occurred
+     * errorAfter  : prefix that was seen before this error occurred
+     * curchar     : the offending character
+     * Note: You can customize the lexical error message by modifying this method.
+     */
+    protected static String LexicalError(boolean eofSeen, int lexState, int errorLine, int errorColumn,
+                                         String errorAfter, char curChar) {
+        return "Lexical error at line " +
+            errorLine + ", column " +
+            errorColumn + ".  Encountered: " +
+            (eofSeen ?
+                "<EOF> " :
+                ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int) curChar + "), ") +
+            "after : \"" + addEscapes(errorAfter) + "\"";
+    }
+
+    /**
+     * You can also modify the body of this method to customize your error messages.
+     * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+     * of end-users concern, so you can return something like :
+     * <p/>
+     * "Internal Error : Please file a bug report .... "
+     * <p/>
+     * from this method for such cases in the release version of your parser.
+     */
+    public String getMessage() {
+        return super.getMessage();
+    }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+    /**
+     * No arg constructor.
+     */
+    public TokenMgrError() {
+    }
+
+    /**
+     * Constructor with message and reason.
+     */
+    public TokenMgrError(String message, int reason) {
+        super(message);
+        errorCode = reason;
+    }
+
+    /**
+     * Full Constructor.
+     */
+    public TokenMgrError(boolean eofSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar,
+                         int reason) {
+        this(LexicalError(eofSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+    }
+}
+/* JavaCC - OriginalChecksum=e960778c8dcd73e167ed5bfddd59f288 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/util/BitsArray.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/util/BitsArray.java b/filter/src/main/java/org/apache/rocketmq/filter/util/BitsArray.java
new file mode 100644
index 0000000..9866854
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/util/BitsArray.java
@@ -0,0 +1,260 @@
+/*
+ * 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.rocketmq.filter.util;
+
+/**
+ * Wrapper of bytes array, in order to operate single bit easily.
+ */
+public class BitsArray implements Cloneable {
+
+    private byte[] bytes;
+    private int bitLength;
+
+    public static BitsArray create(int bitLength) {
+        return new BitsArray(bitLength);
+    }
+
+    public static BitsArray create(byte[] bytes, int bitLength) {
+        return new BitsArray(bytes, bitLength);
+    }
+
+    public static BitsArray create(byte[] bytes) {
+        return new BitsArray(bytes);
+    }
+
+    private BitsArray(int bitLength) {
+        this.bitLength = bitLength;
+        // init bytes
+        int temp = bitLength / Byte.SIZE;
+        if (bitLength % Byte.SIZE > 0) {
+            temp++;
+        }
+        bytes = new byte[temp];
+        for (int i = 0; i < bytes.length; i++) {
+            bytes[i] = (byte) 0x00;
+        }
+    }
+
+    private BitsArray(byte[] bytes, int bitLength) {
+        if (bytes == null || bytes.length < 1) {
+            throw new IllegalArgumentException("Bytes is empty!");
+        }
+
+        if (bitLength < 1) {
+            throw new IllegalArgumentException("Bit is less than 1.");
+        }
+
+        if (bitLength < bytes.length * Byte.SIZE) {
+            throw new IllegalArgumentException("BitLength is less than bytes.length() * " + Byte.SIZE);
+        }
+
+        this.bytes = new byte[bytes.length];
+        System.arraycopy(bytes, 0, this.bytes, 0, this.bytes.length);
+        this.bitLength = bitLength;
+    }
+
+    private BitsArray(byte[] bytes) {
+        if (bytes == null || bytes.length < 1) {
+            throw new IllegalArgumentException("Bytes is empty!");
+        }
+
+        this.bitLength = bytes.length * Byte.SIZE;
+        this.bytes = new byte[bytes.length];
+        System.arraycopy(bytes, 0, this.bytes, 0, this.bytes.length);
+    }
+
+    public int bitLength() {
+        return this.bitLength;
+    }
+
+    public int byteLength() {
+        return this.bytes.length;
+    }
+
+    public byte[] bytes() {
+        return this.bytes;
+    }
+
+    public void xor(final BitsArray other) {
+        checkInitialized(this);
+        checkInitialized(other);
+
+        int minByteLength = Math.min(this.byteLength(), other.byteLength());
+
+        for (int i = 0; i < minByteLength; i++) {
+            this.bytes[i] = (byte) (this.bytes[i] ^ other.getByte(i));
+        }
+    }
+
+    public void xor(int bitPos, boolean set) {
+        checkBitPosition(bitPos, this);
+
+        boolean value = getBit(bitPos);
+        if (value ^ set) {
+            setBit(bitPos, true);
+        } else {
+            setBit(bitPos, false);
+        }
+    }
+
+    public void or(final BitsArray other) {
+        checkInitialized(this);
+        checkInitialized(other);
+
+        int minByteLength = Math.min(this.byteLength(), other.byteLength());
+
+        for (int i = 0; i < minByteLength; i++) {
+            this.bytes[i] = (byte) (this.bytes[i] | other.getByte(i));
+        }
+    }
+
+    public void or(int bitPos, boolean set) {
+        checkBitPosition(bitPos, this);
+
+        if (set) {
+            setBit(bitPos, true);
+        }
+    }
+
+    public void and(final BitsArray other) {
+        checkInitialized(this);
+        checkInitialized(other);
+
+        int minByteLength = Math.min(this.byteLength(), other.byteLength());
+
+        for (int i = 0; i < minByteLength; i++) {
+            this.bytes[i] = (byte) (this.bytes[i] & other.getByte(i));
+        }
+    }
+
+    public void and(int bitPos, boolean set) {
+        checkBitPosition(bitPos, this);
+
+        if (!set) {
+            setBit(bitPos, false);
+        }
+    }
+
+    public void not(int bitPos) {
+        checkBitPosition(bitPos, this);
+
+        setBit(bitPos, !getBit(bitPos));
+    }
+
+    public void setBit(int bitPos, boolean set) {
+        checkBitPosition(bitPos, this);
+        int sub = subscript(bitPos);
+        int pos = position(bitPos);
+        if (set) {
+            this.bytes[sub] = (byte) (this.bytes[sub] | pos);
+        } else {
+            this.bytes[sub] = (byte) (this.bytes[sub] & ~pos);
+        }
+    }
+
+    public void setByte(int bytePos, byte set) {
+        checkBytePosition(bytePos, this);
+
+        this.bytes[bytePos] = set;
+    }
+
+    public boolean getBit(int bitPos) {
+        checkBitPosition(bitPos, this);
+
+        return (this.bytes[subscript(bitPos)] & position(bitPos)) != 0;
+    }
+
+    public byte getByte(int bytePos) {
+        checkBytePosition(bytePos, this);
+
+        return this.bytes[bytePos];
+    }
+
+    protected int subscript(int bitPos) {
+        return bitPos / Byte.SIZE;
+    }
+
+    protected int position(int bitPos) {
+        return 1 << bitPos % Byte.SIZE;
+    }
+
+    protected void checkBytePosition(int bytePos, BitsArray bitsArray) {
+        checkInitialized(bitsArray);
+        if (bytePos > bitsArray.byteLength()) {
+            throw new IllegalArgumentException("BytePos is greater than " + bytes.length);
+        }
+        if (bytePos < 0) {
+            throw new IllegalArgumentException("BytePos is less than 0");
+        }
+    }
+
+    protected void checkBitPosition(int bitPos, BitsArray bitsArray) {
+        checkInitialized(bitsArray);
+        if (bitPos > bitsArray.bitLength()) {
+            throw new IllegalArgumentException("BitPos is greater than " + bitLength);
+        }
+        if (bitPos < 0) {
+            throw new IllegalArgumentException("BitPos is less than 0");
+        }
+    }
+
+    protected void checkInitialized(BitsArray bitsArray) {
+        if (bitsArray.bytes() == null) {
+            throw new RuntimeException("Not initialized!");
+        }
+    }
+
+    public BitsArray clone() {
+        byte[] clone = new byte[this.byteLength()];
+
+        System.arraycopy(this.bytes, 0, clone, 0, this.byteLength());
+
+        return create(clone, bitLength());
+    }
+
+    @Override
+    public String toString() {
+        if (this.bytes == null) {
+            return "null";
+        }
+        StringBuilder stringBuilder = new StringBuilder(this.bytes.length * Byte.SIZE);
+        for (int i = this.bytes.length - 1; i >= 0; i--) {
+
+            int j = Byte.SIZE - 1;
+            if (i == this.bytes.length - 1 && this.bitLength % Byte.SIZE > 0) {
+                // not full byte
+                j = this.bitLength % Byte.SIZE;
+            }
+
+            for (; j >= 0; j--) {
+
+                byte mask = (byte) (1 << j);
+                if ((this.bytes[i] & mask) == mask) {
+                    stringBuilder.append("1");
+                } else {
+                    stringBuilder.append("0");
+                }
+            }
+            if (i % 8 == 0) {
+                stringBuilder.append("\n");
+            }
+        }
+
+        return stringBuilder.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilter.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilter.java b/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilter.java
new file mode 100644
index 0000000..f610906
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilter.java
@@ -0,0 +1,338 @@
+/*
+ * 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.rocketmq.filter.util;
+
+import com.google.common.hash.Hashing;
+
+import java.nio.charset.Charset;
+
+/**
+ * Simple implement of bloom filter.
+ */
+public class BloomFilter {
+
+    public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+    // as error rate, 10/100 = 0.1
+    private int f = 10;
+    private int n = 128;
+
+    // hash function num, by calculation.
+    private int k;
+    // bit count, by calculation.
+    private int m;
+
+    /**
+     * Create bloom filter by error rate and mapping num.
+     *
+     * @param f error rate
+     * @param n num will mapping to bit
+     * @return
+     */
+    public static BloomFilter createByFn(int f, int n) {
+        return new BloomFilter(f, n);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param f error rate
+     * @param n num will mapping to bit
+     */
+    private BloomFilter(int f, int n) {
+        if (f < 1 || f >= 100) {
+            throw new IllegalArgumentException("f must be greater or equal than 1 and less than 100");
+        }
+        if (n < 1) {
+            throw new IllegalArgumentException("n must be greater than 0");
+        }
+
+        this.f = f;
+        this.n = n;
+
+        // set p = e^(-kn/m)
+        // f = (1 - p)^k = e^(kln(1-p))
+        // when p = 0.5, k = ln2 * (m/n), f = (1/2)^k = (0.618)^(m/n)
+        double errorRate = f / 100.0;
+        this.k = (int) Math.ceil(logMN(0.5, errorRate));
+
+        if (this.k < 1) {
+            throw new IllegalArgumentException("Hash function num is less than 1, maybe you should change the value of error rate or bit num!");
+        }
+
+        // m >= n*log2(1/f)*log2(e)
+        this.m = (int) Math.ceil(this.n * logMN(2, 1 / errorRate) * logMN(2, Math.E));
+        // m%8 = 0
+        this.m = (int) (Byte.SIZE * Math.ceil(this.m / (Byte.SIZE * 1.0)));
+    }
+
+    /**
+     * Calculate bit positions of {@code str}.
+     * <p>
+     * See "Less Hashing, Same Performance: Building a Better Bloom Filter" by Adam Kirsch and Michael
+     * Mitzenmacher.
+     * </p>
+     *
+     * @param str
+     * @return
+     */
+    public int[] calcBitPositions(String str) {
+        int[] bitPositions = new int[this.k];
+
+        long hash64 = Hashing.murmur3_128().hashString(str, UTF_8).asLong();
+
+        int hash1 = (int) hash64;
+        int hash2 = (int) (hash64 >>> 32);
+
+        for (int i = 1; i <= this.k; i++) {
+            int combinedHash = hash1 + (i * hash2);
+            // Flip all the bits if it's negative (guaranteed positive number)
+            if (combinedHash < 0) {
+                combinedHash = ~combinedHash;
+            }
+            bitPositions[i - 1] = combinedHash % this.m;
+        }
+
+        return bitPositions;
+    }
+
+    /**
+     * Calculate bit positions of {@code str} to construct {@code BloomFilterData}
+     *
+     * @param str
+     * @return
+     */
+    public BloomFilterData generate(String str) {
+        int[] bitPositions = calcBitPositions(str);
+
+        return new BloomFilterData(bitPositions, this.m);
+    }
+
+    /**
+     * Calculate bit positions of {@code str}, then set the related {@code bits} positions to 1.
+     *
+     * @param str
+     * @param bits
+     */
+    public void hashTo(String str, BitsArray bits) {
+        hashTo(calcBitPositions(str), bits);
+    }
+
+    /**
+     * Set the related {@code bits} positions to 1.
+     *
+     * @param bitPositions
+     * @param bits
+     */
+    public void hashTo(int[] bitPositions, BitsArray bits) {
+        check(bits);
+
+        for (int i : bitPositions) {
+            bits.setBit(i, true);
+        }
+    }
+
+    /**
+     * Extra check:
+     * <li>1. check {@code filterData} belong to this bloom filter.</li>
+     * <p>
+     * Then set the related {@code bits} positions to 1.
+     * </p>
+     *
+     * @param filterData
+     * @param bits
+     */
+    public void hashTo(BloomFilterData filterData, BitsArray bits) {
+        if (!isValid(filterData)) {
+            throw new IllegalArgumentException(
+                String.format("Bloom filter data may not belong to this filter! %s, %s",
+                    filterData, this.toString())
+            );
+        }
+        hashTo(filterData.getBitPos(), bits);
+    }
+
+    /**
+     * Calculate bit positions of {@code str}, then check all the related {@code bits} positions is 1.
+     *
+     * @param str
+     * @param bits
+     * @return true: all the related {@code bits} positions is 1
+     */
+    public boolean isHit(String str, BitsArray bits) {
+        return isHit(calcBitPositions(str), bits);
+    }
+
+    /**
+     * Check all the related {@code bits} positions is 1.
+     *
+     * @param bitPositions
+     * @param bits
+     * @return true: all the related {@code bits} positions is 1
+     */
+    public boolean isHit(int[] bitPositions, BitsArray bits) {
+        check(bits);
+        boolean ret = bits.getBit(bitPositions[0]);
+        for (int i = 1; i < bitPositions.length; i++) {
+            ret &= bits.getBit(bitPositions[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * Check all the related {@code bits} positions is 1.
+     *
+     * @param filterData
+     * @param bits
+     * @return true: all the related {@code bits} positions is 1
+     */
+    public boolean isHit(BloomFilterData filterData, BitsArray bits) {
+        if (!isValid(filterData)) {
+            throw new IllegalArgumentException(
+                String.format("Bloom filter data may not belong to this filter! %s, %s",
+                    filterData, this.toString())
+            );
+        }
+        return isHit(filterData.getBitPos(), bits);
+    }
+
+    /**
+     * Check whether one of {@code bitPositions} has been occupied.
+     *
+     * @param bitPositions
+     * @param bits
+     * @return true: if all positions have been occupied.
+     */
+    public boolean checkFalseHit(int[] bitPositions, BitsArray bits) {
+        for (int j = 0; j < bitPositions.length; j++) {
+            int pos = bitPositions[j];
+
+            // check position of bits has been set.
+            // that mean no one occupy the position.
+            if (!bits.getBit(pos)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    protected void check(BitsArray bits) {
+        if (bits.bitLength() != this.m) {
+            throw new IllegalArgumentException(
+                String.format("Length(%d) of bits in BitsArray is not equal to %d!", bits.bitLength(), this.m)
+            );
+        }
+    }
+
+    /**
+     * Check {@code BloomFilterData} is valid, and belong to this bloom filter.
+     * <li>1. not null</li>
+     * <li>2. {@link org.apache.rocketmq.filter.util.BloomFilterData#getBitNum} must be equal to {@code m} </li>
+     * <li>3. {@link org.apache.rocketmq.filter.util.BloomFilterData#getBitPos} is not null</li>
+     * <li>4. {@link org.apache.rocketmq.filter.util.BloomFilterData#getBitPos}'s length is equal to {@code k}</li>
+     *
+     * @param filterData
+     * @return
+     */
+    public boolean isValid(BloomFilterData filterData) {
+        if (filterData == null
+            || filterData.getBitNum() != this.m
+            || filterData.getBitPos() == null
+            || filterData.getBitPos().length != this.k) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * error rate.
+     *
+     * @return
+     */
+    public int getF() {
+        return f;
+    }
+
+    /**
+     * expect mapping num.
+     *
+     * @return
+     */
+    public int getN() {
+        return n;
+    }
+
+    /**
+     * hash function num.
+     *
+     * @return
+     */
+    public int getK() {
+        return k;
+    }
+
+    /**
+     * total bit num.
+     *
+     * @return
+     */
+    public int getM() {
+        return m;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (!(o instanceof BloomFilter))
+            return false;
+
+        BloomFilter that = (BloomFilter) o;
+
+        if (f != that.f)
+            return false;
+        if (k != that.k)
+            return false;
+        if (m != that.m)
+            return false;
+        if (n != that.n)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = f;
+        result = 31 * result + n;
+        result = 31 * result + k;
+        result = 31 * result + m;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("f: %d, n: %d, k: %d, m: %d", f, n, k, m);
+    }
+
+    protected double logMN(double m, double n) {
+        return Math.log(n) / Math.log(m);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rocketmq/blob/9eeb2f7e/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilterData.java
----------------------------------------------------------------------
diff --git a/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilterData.java b/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilterData.java
new file mode 100644
index 0000000..de02d92
--- /dev/null
+++ b/filter/src/main/java/org/apache/rocketmq/filter/util/BloomFilterData.java
@@ -0,0 +1,83 @@
+/*
+ * 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.rocketmq.filter.util;
+
+import java.util.Arrays;
+
+/**
+ * Data generated by bloom filter, include:
+ * <li>1. Bit positions allocated to requester;</li>
+ * <li>2. Total bit num when allocating;</li>
+ */
+public class BloomFilterData {
+
+    private int[] bitPos;
+    private int bitNum;
+
+    public BloomFilterData() {
+    }
+
+    public BloomFilterData(int[] bitPos, int bitNum) {
+        this.bitPos = bitPos;
+        this.bitNum = bitNum;
+    }
+
+    public int[] getBitPos() {
+        return bitPos;
+    }
+
+    public int getBitNum() {
+        return bitNum;
+    }
+
+    public void setBitPos(final int[] bitPos) {
+        this.bitPos = bitPos;
+    }
+
+    public void setBitNum(final int bitNum) {
+        this.bitNum = bitNum;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (!(o instanceof BloomFilterData)) return false;
+
+        final BloomFilterData that = (BloomFilterData) o;
+
+        if (bitNum != that.bitNum) return false;
+        if (!Arrays.equals(bitPos, that.bitPos)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = bitPos != null ? Arrays.hashCode(bitPos) : 0;
+        result = 31 * result + bitNum;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "BloomFilterData{" +
+            "bitPos=" + Arrays.toString(bitPos) +
+            ", bitNum=" + bitNum +
+            '}';
+    }
+}