001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mq.selectors;
023:
024: import java.util.HashMap;
025: import java.util.Iterator;
026:
027: import javax.jms.DeliveryMode;
028: import javax.jms.InvalidSelectorException;
029: import javax.jms.JMSException;
030:
031: import org.jboss.logging.Logger;
032: import org.jboss.mq.SpyMessage;
033: import org.jboss.util.NestedRuntimeException;
034:
035: /**
036: * This class implements a Message Selector.
037: *
038: * @author Norbert Lataille (Norbert.Lataille@m4x.org)
039: * @author Juha Lindfors (jplindfo@helsinki.fi)
040: * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
041: * @author Scott.Stark@jboss.org
042: * @author adrian@jboss.com
043: * @version $Revision: 57198 $
044: */
045: public class Selector {
046: /** The logging interface */
047: static Logger cat = Logger.getLogger(Selector.class);
048:
049: /** The ISelectorParser implementation class */
050: private static Class parserClass = SelectorParser.class;
051:
052: /** The system property property for numeric delivery mode */
053: public static final String USE_NUMERIC_DELIVERY_MODE = "org.jboss.mq.selectors.useNumericDeliveryMode";
054:
055: /** Backwards compatibility flag */
056: private static boolean useNumericDeliveryMode;
057:
058: public String selector;
059:
060: public HashMap identifiers;
061:
062: public Object result;
063:
064: private Class resultType;
065:
066: static {
067: try {
068: String property = System.getProperty(
069: USE_NUMERIC_DELIVERY_MODE, "false");
070: useNumericDeliveryMode = Boolean.valueOf(property)
071: .booleanValue();
072: } catch (Exception ignored) {
073: cat.trace("Cannot get property "
074: + USE_NUMERIC_DELIVERY_MODE, ignored);
075: }
076: }
077:
078: /**
079: * Get the class that implements the ISelectorParser interface to be used by
080: * Selector instances.
081: */
082: public static Class getSelectorParserClass() {
083: return Selector.parserClass;
084: }
085:
086: /**
087: * Set the class that implements the ISelectorParser interface to be used by
088: * Selector instances.
089: *
090: * @param parserClass the ISelectorParser implementation. This must have a
091: * public no-arg constructor.
092: */
093: public static void setSelectorParserClass(Class parserClass) {
094: Selector.parserClass = parserClass;
095: }
096:
097: public Selector(String sel) throws InvalidSelectorException {
098: selector = sel;
099: identifiers = new HashMap();
100:
101: try {
102: ISelectorParser bob = (ISelectorParser) parserClass
103: .newInstance();
104: result = bob.parse(sel, identifiers);
105: resultType = result.getClass();
106: } catch (Exception e) {
107: InvalidSelectorException exception = new InvalidSelectorException(
108: "The selector is invalid: " + sel);
109: exception.setLinkedException(e);
110: throw exception;
111: } catch (Error e) {
112: InvalidSelectorException exception = new InvalidSelectorException(
113: "The selector is invalid: " + sel);
114: exception.setLinkedException(new NestedRuntimeException(e));
115: throw exception;
116: }
117: }
118:
119: public synchronized boolean test(SpyMessage.Header mes)
120: throws JMSException {
121: try {
122: // Set the identifiers values
123: Iterator i = identifiers.values().iterator();
124:
125: while (i.hasNext()) {
126: Identifier id = (Identifier) i.next();
127: Object find = mes.jmsProperties.get(id.name);
128:
129: if (find == null)
130: find = getHeaderFieldReferences(mes, id.name);
131:
132: if (find == null)
133: id.value = null;
134: else {
135: Class type = find.getClass();
136: if (type.equals(Boolean.class)
137: || type.equals(String.class)
138: || type.equals(Double.class)
139: || type.equals(Float.class)
140: || type.equals(Integer.class)
141: || type.equals(Long.class)
142: || type.equals(Short.class)
143: || type.equals(Byte.class))
144: id.value = find;
145: else
146: throw new Exception("Bad property '" + id.name
147: + "' type: " + type);
148: }
149: }
150:
151: // Compute the result of this operator
152: Object res;
153:
154: if (resultType.equals(Identifier.class))
155: res = ((Identifier) result).value;
156: else if (resultType.equals(Operator.class)) {
157: Operator op = (Operator) result;
158: res = op.apply();
159: } else
160: res = result;
161:
162: if (res == null)
163: return false;
164:
165: if (!(res.getClass().equals(Boolean.class)))
166: throw new Exception("Bad object type: " + res);
167:
168: return ((Boolean) res).booleanValue();
169: } catch (Exception e) {
170: cat.warn("Invalid selector: " + selector, e);
171: return false;
172: }
173: }
174:
175: public boolean test(SpyMessage msg) throws JMSException {
176: return test(msg.header);
177: }
178:
179: // [JPL]
180: private Object getHeaderFieldReferences(SpyMessage.Header header,
181: String idName) throws JMSException {
182: // JMS 3.8.1.1 -- Message header field references are restricted to:
183: // JMSDeliveryMode, JMSPriority, JMSMessageID,
184: // JMSTimeStamp, JMSCorrelationID and JMSType
185: //
186: if (idName.equals("JMSDeliveryMode")) {
187: if (useNumericDeliveryMode)
188: return new Integer(header.jmsDeliveryMode);
189: // JMS 3.8.1.3 -- Use 'PERISTENT' and 'NON_PERSISTENT'
190: else if (header.jmsDeliveryMode == DeliveryMode.NON_PERSISTENT)
191: return "NON_PERSISTENT";
192: else
193: return "PERSISTENT";
194: } else if (idName.equals("JMSPriority"))
195: return new Integer(header.jmsPriority);
196: else if (idName.equals("JMSMessageID"))
197: return header.jmsMessageID;
198: else if (idName.equals("JMSTimestamp"))
199: return new Long(header.jmsTimeStamp);
200: else if (idName.equals("JMSCorrelationID"))
201: return header.jmsCorrelationIDString;
202: else if (idName.equals("JMSType"))
203: return header.jmsType;
204: else
205: return null;
206: }
207: }
|