diff --git a/activemq-core/src/main/grammar/SelectorParser.jj b/activemq-core/src/main/grammar/SelectorParser.jj index bedf343056..9a167b3bdc 100755 --- a/activemq-core/src/main/grammar/SelectorParser.jj +++ b/activemq-core/src/main/grammar/SelectorParser.jj @@ -57,6 +57,7 @@ import java.util.*; import javax.jms.InvalidSelectorException; import org.apache.activemq.filter.*; +import org.apache.activemq.util.LRUCache; /** * JMS Selector Parser generated by JavaCC @@ -65,22 +66,46 @@ import org.apache.activemq.filter.*; */ public class SelectorParser { - public SelectorParser() { - this(new StringReader("")); + private static final LRUCache cache = new LRUCache(100); + + public static BooleanExpression parse(String sql) throws InvalidSelectorException { + Object result = cache.get(sql); + if (result instanceof InvalidSelectorException) { + throw (InvalidSelectorException) result; + } else if (result instanceof BooleanExpression) { + return (BooleanExpression) result; + } else { + try { + BooleanExpression e = new SelectorParser(sql).parse(); + cache.put(sql, e); + return e; + } catch (InvalidSelectorException t) { + cache.put(sql, t); + throw t; + } + } } - public BooleanExpression parse(String sql) throws InvalidSelectorException { - this.ReInit(new StringReader(sql)); + public static void clearCache() { + cache.clear(); + } + private String sql; + + protected SelectorParser(String sql) { + this(new StringReader(sql)); + this.sql = sql; + } + + protected BooleanExpression parse() throws InvalidSelectorException { try { return this.JmsSelector(); - } - catch (Throwable e) { - throw (InvalidSelectorException)new InvalidSelectorException(sql).initCause(e); } - + catch (Throwable e) { + throw (InvalidSelectorException) new InvalidSelectorException(sql).initCause(e); + } } - + private BooleanExpression asBooleanExpression(Expression value) throws ParseException { if (value instanceof BooleanExpression) { return (BooleanExpression) value; diff --git a/activemq-core/src/main/java/org/apache/activemq/ActiveMQInputStream.java b/activemq-core/src/main/java/org/apache/activemq/ActiveMQInputStream.java index 9348a7fa19..fb82b1f104 100644 --- a/activemq-core/src/main/java/org/apache/activemq/ActiveMQInputStream.java +++ b/activemq-core/src/main/java/org/apache/activemq/ActiveMQInputStream.java @@ -91,7 +91,7 @@ public class ActiveMQInputStream extends InputStream implements ActiveMQDispatch selector = "JMSType='org.apache.activemq.Stream'"; } - new SelectorParser().parse(selector); + SelectorParser.parse(selector); this.info.setSelector(selector); this.info.setPrefetchSize(prefetch); diff --git a/activemq-core/src/main/java/org/apache/activemq/ActiveMQMessageConsumer.java b/activemq-core/src/main/java/org/apache/activemq/ActiveMQMessageConsumer.java index 91b9308668..7bd9d60f05 100755 --- a/activemq-core/src/main/java/org/apache/activemq/ActiveMQMessageConsumer.java +++ b/activemq-core/src/main/java/org/apache/activemq/ActiveMQMessageConsumer.java @@ -200,12 +200,12 @@ public class ActiveMQMessageConsumer implements MessageAvailableConsumer, StatsC this.info.setBrowser(browser); if (selector != null && selector.trim().length() != 0) { // Validate the selector - new SelectorParser().parse(selector); + SelectorParser.parse(selector); this.info.setSelector(selector); this.selector = selector; } else if (info.getSelector() != null) { // Validate the selector - new SelectorParser().parse(this.info.getSelector()); + SelectorParser.parse(this.info.getSelector()); this.selector = this.info.getSelector(); } else { this.selector = null; diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java b/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java index 98c6f2d87b..a1cade9451 100644 --- a/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java @@ -35,6 +35,7 @@ import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.activemq.ActiveMQConnectionMetaData; import org.apache.activemq.Service; +import org.apache.activemq.selector.SelectorParser; import org.apache.activemq.advisory.AdvisoryBroker; import org.apache.activemq.broker.cluster.ConnectionSplitBroker; import org.apache.activemq.broker.ft.MasterConnector; @@ -530,6 +531,8 @@ public class BrokerService implements Service { } stopper.stop(getManagementContext()); } + // Clear SelectorParser cache to free memory + SelectorParser.clearCache(); stopped.set(true); stoppedLatch.countDown(); LOG.info("ActiveMQ JMS Message Broker (" + getBrokerName() + ", " + brokerId + ") stopped"); diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/jmx/DestinationView.java b/activemq-core/src/main/java/org/apache/activemq/broker/jmx/DestinationView.java index 5b50f7592f..fff4a43e57 100644 --- a/activemq-core/src/main/java/org/apache/activemq/broker/jmx/DestinationView.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/jmx/DestinationView.java @@ -141,7 +141,7 @@ public class DestinationView implements DestinationViewMBean { MessageEvaluationContext ctx = new MessageEvaluationContext(); ctx.setDestination(destination.getActiveMQDestination()); - BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector); + BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector); for (int i = 0; i < messages.length; i++) { try { @@ -186,7 +186,7 @@ public class DestinationView implements DestinationViewMBean { MessageEvaluationContext ctx = new MessageEvaluationContext(); ctx.setDestination(destination.getActiveMQDestination()); - BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector); + BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector); for (int i = 0; i < messages.length; i++) { try { @@ -224,7 +224,7 @@ public class DestinationView implements DestinationViewMBean { MessageEvaluationContext ctx = new MessageEvaluationContext(); ctx.setDestination(destination.getActiveMQDestination()); - BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector); + BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector); for (int i = 0; i < messages.length; i++) { try { diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/region/AbstractSubscription.java b/activemq-core/src/main/java/org/apache/activemq/broker/region/AbstractSubscription.java index f7dd16fff7..5a491ddf8f 100755 --- a/activemq-core/src/main/java/org/apache/activemq/broker/region/AbstractSubscription.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/region/AbstractSubscription.java @@ -60,7 +60,7 @@ public abstract class AbstractSubscription implements Subscription { private static BooleanExpression parseSelector(ConsumerInfo info) throws InvalidSelectorException { BooleanExpression rc = null; if (info.getSelector() != null) { - rc = new SelectorParser().parse(info.getSelector()); + rc = SelectorParser.parse(info.getSelector()); } if (info.isNoLocal()) { if (rc == null) { diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/region/Queue.java b/activemq-core/src/main/java/org/apache/activemq/broker/region/Queue.java index 5da454a257..d46283148f 100755 --- a/activemq-core/src/main/java/org/apache/activemq/broker/region/Queue.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/region/Queue.java @@ -1105,7 +1105,7 @@ public class Queue extends BaseDestination implements Task { } protected MessageReferenceFilter createSelectorFilter(String selector) throws InvalidSelectorException { - final BooleanExpression selectorExpression = new SelectorParser().parse(selector); + final BooleanExpression selectorExpression = SelectorParser.parse(selector); return new MessageReferenceFilter() { public boolean evaluate(ConnectionContext context, MessageReference r) throws JMSException { diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/region/virtual/FilteredDestination.java b/activemq-core/src/main/java/org/apache/activemq/broker/region/virtual/FilteredDestination.java index bc648f11fa..32322a604d 100644 --- a/activemq-core/src/main/java/org/apache/activemq/broker/region/virtual/FilteredDestination.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/region/virtual/FilteredDestination.java @@ -66,7 +66,7 @@ public class FilteredDestination { */ public void setSelector(String selector) throws InvalidSelectorException { this.selector = selector; - setFilter(new SelectorParser().parse(selector)); + setFilter(SelectorParser.parse(selector)); } public BooleanExpression getFilter() { diff --git a/activemq-core/src/test/java/org/apache/activemq/selector/SelectorParserTest.java b/activemq-core/src/test/java/org/apache/activemq/selector/SelectorParserTest.java index 6a0be32279..95e84e679c 100755 --- a/activemq-core/src/test/java/org/apache/activemq/selector/SelectorParserTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/selector/SelectorParserTest.java @@ -68,6 +68,6 @@ public class SelectorParserTest extends TestCase { } protected BooleanExpression parse(String text) throws Exception { - return new SelectorParser().parse(text); + return SelectorParser.parse(text); } } diff --git a/activemq-core/src/test/java/org/apache/activemq/selector/SelectorTest.java b/activemq-core/src/test/java/org/apache/activemq/selector/SelectorTest.java index f2ef2bd431..69d7f9cf5f 100755 --- a/activemq-core/src/test/java/org/apache/activemq/selector/SelectorTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/selector/SelectorTest.java @@ -352,14 +352,14 @@ public class SelectorTest extends TestCase { protected void assertInvalidSelector(Message message, String text) throws JMSException { try { - new SelectorParser().parse(text); + SelectorParser.parse(text); fail("Created a valid selector"); } catch (InvalidSelectorException e) { } } protected void assertSelector(Message message, String text, boolean expected) throws JMSException { - BooleanExpression selector = new SelectorParser().parse(text); + BooleanExpression selector = SelectorParser.parse(text); assertTrue("Created a valid selector", selector != null); MessageEvaluationContext context = new MessageEvaluationContext(); context.setMessageReference((org.apache.activemq.command.Message)message); diff --git a/activemq-ra/src/main/java/org/apache/activemq/ra/ActiveMQActivationSpec.java b/activemq-ra/src/main/java/org/apache/activemq/ra/ActiveMQActivationSpec.java index 4e542a79f0..68bacd934a 100644 --- a/activemq-ra/src/main/java/org/apache/activemq/ra/ActiveMQActivationSpec.java +++ b/activemq-ra/src/main/java/org/apache/activemq/ra/ActiveMQActivationSpec.java @@ -165,7 +165,7 @@ public class ActiveMQActivationSpec implements MessageActivationSpec, Serializab public boolean isValidMessageSelector(List errorMessages) { try { if (!isEmpty(messageSelector)) { - new SelectorParser().parse(messageSelector); + SelectorParser.parse(messageSelector); } return true; } catch (Throwable e) {