View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2000-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: MessageProperties.java,v 1.1 2004/11/26 01:50:43 tanderson Exp $
44   *
45   * Date         Author  Changes
46   * 02/26/2000   jimm    Created
47   */
48  
49  package org.exolab.jms.message;
50  
51  import java.io.Externalizable;
52  import java.io.IOException;
53  import java.io.ObjectInput;
54  import java.io.ObjectOutput;
55  import java.util.Collections;
56  import java.util.Enumeration;
57  import java.util.HashMap;
58  
59  import javax.jms.JMSException;
60  import javax.jms.MessageFormatException;
61  
62  
63  /***
64   * This class provides properties for messages
65   *
66   * @version     $Revision: 1.1 $ $Date: 2004/11/26 01:50:43 $
67   * @author      <a href="mailto:mourikis@intalio.com">Jim Mourikis</a>
68   * @author      <a href="mailto:tima@intalio.com">Tim Anderson</a>
69   */
70  class MessageProperties implements Cloneable, Externalizable {
71  
72      /***
73       * The map containing of properties
74       */
75      private HashMap _properties = new HashMap(20);
76  
77      /***
78       * Object version no. for serialization
79       */
80      static final long serialVersionUID = 1;
81  
82      /***
83       * Illegal names
84       */
85      private static final String[] RESERVED_WORDS = {
86          "and", "between", "escape", "in", "is", "like", "false", "null", "or",
87          "not", "true"};
88  
89      private static final String GROUP_ID = "JMSXGroupID";
90      private static final String GROUP_SEQ = "JMSXGroupSeq";
91  
92      /***
93       * Recognized provider property names that may be set by clients, and
94       * their expected types
95       */
96      private static final Object[][] JMSX_CLIENT_NAMES = {
97          {GROUP_ID, String.class},
98          {GROUP_SEQ, Integer.class}};
99  
100     /***
101      * Default constructor to support externalization
102      */
103     public MessageProperties() {
104     }
105 
106     /***
107      * Clone an instance of this object
108      *
109      * @return a copy of this object
110      * @throws CloneNotSupportedException if object or attributes not cloneable
111      */
112     public Object clone() throws CloneNotSupportedException {
113         MessageProperties result = new MessageProperties();
114         result._properties = (HashMap) _properties.clone();
115         return result;
116     }
117 
118     /***
119      * Handle serialization.
120      * Just serialize the whole thing for this release.
121      *
122      * @param out the stream to write the object to
123      * @throws IOException if the object cannot be written
124      */
125     public void writeExternal(ObjectOutput out) throws IOException {
126         out.writeLong(serialVersionUID);
127         out.writeObject(_properties);
128     }
129 
130     /***
131      * Read in the serialized object and assign all values from the stream.
132      * Ensure the version is one that is currently supported.
133      *
134      * @param in the input stream
135      * @throws IOException if an I/O error occurs
136      * @throws ClassNotFoundException if the class for an object being
137      * restored cannot be found.
138      */
139     public void readExternal(ObjectInput in)
140         throws IOException, ClassNotFoundException {
141         long version = in.readLong();
142         if (version == serialVersionUID) {
143             _properties = (HashMap) in.readObject();
144         } else {
145             throw new IOException("Incorrect version enountered: " +
146                 version + " This version = " +
147                 serialVersionUID);
148         }
149     }
150 
151     /***
152      * Clear out all existing properties.
153      */
154     public void clearProperties() {
155         _properties.clear();
156     }
157 
158     public boolean propertyExists(String name) {
159         return _properties.containsKey(name);
160     }
161 
162     public boolean getBooleanProperty(String name) throws JMSException {
163         return FormatConverter.getBoolean(_properties.get(name));
164     }
165 
166     public byte getByteProperty(String name) throws JMSException {
167         return FormatConverter.getByte(_properties.get(name));
168     }
169 
170     public short getShortProperty(String name) throws JMSException {
171         return FormatConverter.getShort(_properties.get(name));
172     }
173 
174     public int getIntProperty(String name) throws JMSException {
175         return FormatConverter.getInt(_properties.get(name));
176     }
177 
178     public long getLongProperty(String name) throws JMSException {
179         return FormatConverter.getLong(_properties.get(name));
180     }
181 
182     public float getFloatProperty(String name) throws JMSException {
183         return FormatConverter.getFloat(_properties.get(name));
184     }
185 
186     public double getDoubleProperty(String name) throws JMSException {
187         return FormatConverter.getDouble(_properties.get(name));
188     }
189 
190     public String getStringProperty(String name) throws JMSException {
191         return FormatConverter.getString(_properties.get(name));
192     }
193 
194     public Object getObjectProperty(String name) throws JMSException {
195         return _properties.get(name);
196     }
197 
198     public Enumeration getPropertyNames() {
199         return Collections.enumeration(_properties.keySet());
200     }
201 
202     public void setBooleanProperty(String name, boolean value)
203         throws JMSException {
204         setProperty(name, new Boolean(value));
205     }
206 
207     public void setByteProperty(String name, byte value) throws JMSException {
208         setProperty(name, new Byte(value));
209     }
210 
211     public void setShortProperty(String name, short value)
212         throws JMSException {
213         setProperty(name, new Short(value));
214     }
215 
216     public void setIntProperty(String name, int value) throws JMSException {
217         setProperty(name, new Integer(value));
218     }
219 
220     public void setLongProperty(String name, long value) throws JMSException {
221         setProperty(name, new Long(value));
222     }
223 
224     public void setFloatProperty(String name, float value)
225         throws JMSException {
226         setProperty(name, new Float(value));
227     }
228 
229     public void setDoubleProperty(String name, double value)
230         throws JMSException {
231         setProperty(name, new Double(value));
232     }
233 
234     public void setStringProperty(String name, String value)
235         throws JMSException {
236         setProperty(name, value);
237     }
238 
239     public void setObjectProperty(String name, Object value)
240         throws JMSException {
241         if (value instanceof Boolean || value instanceof Byte ||
242             value instanceof Short || value instanceof Integer ||
243             value instanceof Long || value instanceof Float ||
244             value instanceof Double || value instanceof String ||
245             (value == null)) {
246             setProperty(name, value);
247         } else {
248             throw new MessageFormatException(
249                 "Message.setObjectProperty() does not support objects of " +
250                 "type=" + value.getClass().getName());
251         }
252     }
253 
254     public void setJMSXRcvTimestamp(long value) {
255         _properties.put("JMSXRcvTimestamp", new Long(value));
256     }
257 
258     protected void setProperty(String name, Object value) throws JMSException {
259         if (name == null) {
260             throw new JMSException("<null> is not a valid property name");
261         }
262         char[] chars = name.toCharArray();
263         if (chars.length == 0) {
264             throw new JMSException("zero-length name is not a valid " +
265                 "property name");
266         }
267         if (!Character.isJavaIdentifierStart(chars[0])) {
268             throw new JMSException("name=" + name + " is not a valid " +
269                 "property name");
270         }
271         for (int i = 1; i < chars.length; ++i) {
272             if (!Character.isJavaIdentifierPart(chars[i])) {
273                 throw new JMSException("name=" + name + " is not a valid " +
274                     "property name");
275             }
276         }
277         for (int i = 0; i < RESERVED_WORDS.length; ++i) {
278             if (name.equalsIgnoreCase(RESERVED_WORDS[i])) {
279                 throw new JMSException("name=" + name + " is a reserved " +
280                     "word; it cannot be used as a " +
281                     "property name");
282             }
283         }
284 
285         if (name.startsWith("JMSX")) {
286             boolean found = false;
287             for (int i = 0; i < JMSX_CLIENT_NAMES.length; ++i) {
288                 Object[] types = JMSX_CLIENT_NAMES[i];
289                 if (types[0].equals(name)) {
290                     if (value == null) {
291                         throw new MessageFormatException("Property=" + name +
292                             " may not be null");
293                     }
294                     Class type = (Class) types[1];
295                     if (!type.equals(value.getClass())) {
296                         throw new MessageFormatException(
297                             "Expected type=" + type.getName() +
298                             " for property=" + name + ", but got type=" +
299                             value.getClass().getName());
300                     }
301                     if (name.equals(GROUP_SEQ) &&
302                         ((Integer) value).intValue() <= 0) {
303                         throw new JMSException(
304                             GROUP_SEQ + " must have a value > 0");
305                     }
306                     found = true;
307                     break;
308                 }
309             }
310             if (!found) {
311                 throw new JMSException("Property=" + name +
312                     " cannot be set by clients");
313             }
314         }
315 
316         _properties.put(name, value);
317     }
318 
319 } //-- MessageProperties