KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > DynaProperty


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17
18 package org.apache.commons.beanutils;
19
20
21 import java.io.IOException JavaDoc;
22 import java.io.Serializable JavaDoc;
23 import java.io.ObjectOutputStream JavaDoc;
24 import java.io.ObjectInputStream JavaDoc;
25 import java.io.StreamCorruptedException JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28
29
30 /**
31  * <p>The metadata describing an individual property of a DynaBean.</p>
32  *
33  * <p>The meta contains an <em>optional</em> content type property ({@link #getContentType})
34  * for use by mapped and iterated properties.
35  * A mapped or iterated property may choose to indicate the type it expects.
36  * The DynaBean implementation may choose to enforce this type on its entries.
37  * Alternatively, an implementatin may choose to ignore this property.
38  * All keys for maps must be of type String so no meta data is needed for map keys.</p>
39  *
40  * @author Craig R. McClanahan
41  * @version $Revision: 1.13 $ $Date: 2004/02/28 13:18:33 $
42  */

43
44 public class DynaProperty implements Serializable JavaDoc {
45
46     // ----------------------------------------------------------- Constants
47

48     /*
49      * There are issues with serializing primitive class types on certain JVM versions
50      * (including java 1.3).
51      * This class uses a custom serialization implementation that writes an integer
52      * for these primitive class.
53      * This list of constants are the ones used in serialization.
54      * If these values are changed, then older versions will no longer be read correctly
55      */

56     private static final int BOOLEAN_TYPE = 1;
57     private static final int BYTE_TYPE = 2;
58     private static final int CHAR_TYPE = 3;
59     private static final int DOUBLE_TYPE = 4;
60     private static final int FLOAT_TYPE = 5;
61     private static final int INT_TYPE = 6;
62     private static final int LONG_TYPE = 7;
63     private static final int SHORT_TYPE = 8;
64     
65
66     // ----------------------------------------------------------- Constructors
67

68
69     /**
70      * Construct a property that accepts any data type.
71      *
72      * @param name Name of the property being described
73      */

74     public DynaProperty(String JavaDoc name) {
75
76         this(name, Object JavaDoc.class);
77
78     }
79
80
81     /**
82      * Construct a property of the specified data type.
83      *
84      * @param name Name of the property being described
85      * @param type Java class representing the property data type
86      */

87     public DynaProperty(String JavaDoc name, Class JavaDoc type) {
88
89         super();
90         this.name = name;
91         this.type = type;
92
93     }
94     
95     /**
96      * Construct an indexed or mapped <code>DynaProperty</code> that supports (pseudo)-introspection
97      * of the content type.
98      *
99      * @param name Name of the property being described
100      * @param type Java class representing the property data type
101      * @param contentType Class that all indexed or mapped elements are instances of
102      */

103     public DynaProperty(String JavaDoc name, Class JavaDoc type, Class JavaDoc contentType) {
104
105         super();
106         this.name = name;
107         this.type = type;
108         this.contentType = contentType;
109         
110     }
111
112     // ------------------------------------------------------------- Properties
113

114     /** Property name */
115     protected String JavaDoc name = null;
116     /**
117      * Get the name of this property.
118      */

119     public String JavaDoc getName() {
120         return (this.name);
121     }
122     
123     /** Property type */
124     protected transient Class JavaDoc type = null;
125     /**
126      * <p>Gets the Java class representing the data type of the underlying property
127      * values.</p>
128      *
129      * <p>There are issues with serializing primitive class types on certain JVM versions
130      * (including java 1.3).
131      * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
132      *
133      * <p><strong>Please leave this field as <code>transient</code></strong></p>
134      */

135     public Class JavaDoc getType() {
136         return (this.type);
137     }
138     
139     
140     /** The <em>(optional)</em> type of content elements for indexed <code>DynaProperty</code> */
141     protected transient Class JavaDoc contentType;
142     /**
143      * Gets the <em>(optional)</em> type of the indexed content for <code>DynaProperty</code>'s
144      * that support this feature.
145      *
146      * <p>There are issues with serializing primitive class types on certain JVM versions
147      * (including java 1.3).
148      * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
149      *
150      * @return the Class for the content type if this is an indexed <code>DynaProperty</code>
151      * and this feature is supported. Otherwise null.
152      */

153     public Class JavaDoc getContentType() {
154         return contentType;
155     }
156     
157     // --------------------------------------------------------- Public Methods
158

159
160     /**
161      * Does this property represent an indexed value (ie an array or List)?
162      */

163     public boolean isIndexed() {
164
165         if (type == null) {
166             return (false);
167         } else if (type.isArray()) {
168             return (true);
169         } else if (List JavaDoc.class.isAssignableFrom(type)) {
170             return (true);
171         } else {
172             return (false);
173         }
174
175     }
176
177
178     /**
179      * Does this property represent a mapped value (ie a Map)?
180      */

181     public boolean isMapped() {
182
183         if (type == null) {
184             return (false);
185         } else {
186             return (Map JavaDoc.class.isAssignableFrom(type));
187         }
188
189     }
190
191
192     /**
193      * Return a String representation of this Object.
194      */

195     public String JavaDoc toString() {
196
197         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("DynaProperty[name=");
198         sb.append(this.name);
199         sb.append(",type=");
200         sb.append(this.type);
201         if (isMapped() || isIndexed()) {
202             sb.append(" <").append(this.contentType).append(">");
203         }
204         sb.append("]");
205         return (sb.toString());
206
207     }
208
209     // --------------------------------------------------------- Serialization helper methods
210

211     /**
212      * Writes this object safely.
213      * There are issues with serializing primitive class types on certain JVM versions
214      * (including java 1.3).
215      * This method provides a workaround.
216      */

217     private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
218         
219         writeAnyClass(this.type,out);
220         
221         if (isMapped() || isIndexed()) {
222             writeAnyClass(this.contentType,out);
223         }
224         
225         // write out other values
226
out.defaultWriteObject();
227     }
228
229     /**
230      * Write a class using safe encoding to workaround java 1.3 serialization bug.
231      */

232     private void writeAnyClass(Class JavaDoc clazz, ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
233         // safely write out any class
234
int primitiveType = 0;
235         if (Boolean.TYPE.equals(clazz)) {
236             primitiveType = BOOLEAN_TYPE;
237         } else if (Byte.TYPE.equals(clazz)) {
238             primitiveType = BYTE_TYPE;
239         } else if (Character.TYPE.equals(clazz)) {
240             primitiveType = CHAR_TYPE;
241         } else if (Double.TYPE.equals(clazz)) {
242             primitiveType = DOUBLE_TYPE;
243         } else if (Float.TYPE.equals(clazz)) {
244             primitiveType = FLOAT_TYPE;
245         } else if (Integer.TYPE.equals(clazz)) {
246             primitiveType = INT_TYPE;
247         } else if (Long.TYPE.equals(clazz)) {
248             primitiveType = LONG_TYPE;
249         } else if (Short.TYPE.equals(clazz)) {
250             primitiveType = SHORT_TYPE;
251         }
252         
253         if (primitiveType == 0) {
254             // then it's not a primitive type
255
out.writeBoolean(false);
256             out.writeObject(clazz);
257         } else {
258             // we'll write out a constant instead
259
out.writeBoolean(true);
260             out.writeInt(primitiveType);
261         }
262     }
263     
264     /**
265      * Reads field values for this object safely.
266      * There are issues with serializing primitive class types on certain JVM versions
267      * (including java 1.3).
268      * This method provides a workaround.
269      *
270      * @throws StreamCorruptedException when the stream data values are outside expected range
271      */

272     private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
273         
274         this.type = readAnyClass(in);
275         
276         if (isMapped() || isIndexed()) {
277             this.contentType = readAnyClass(in);
278         }
279         
280         // read other values
281
in.defaultReadObject();
282     }
283     
284
285     /**
286      * Reads a class using safe encoding to workaround java 1.3 serialization bug.
287      */

288     private Class JavaDoc readAnyClass(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
289         // read back type class safely
290
if (in.readBoolean()) {
291             // it's a type constant
292
switch (in.readInt()) {
293             
294                 case BOOLEAN_TYPE: return Boolean.TYPE;
295                 case BYTE_TYPE: return Byte.TYPE;
296                 case CHAR_TYPE: return Character.TYPE;
297                 case DOUBLE_TYPE: return Double.TYPE;
298                 case FLOAT_TYPE: return Float.TYPE;
299                 case INT_TYPE: return Integer.TYPE;
300                 case LONG_TYPE: return Long.TYPE;
301                 case SHORT_TYPE: return Short.TYPE;
302                 default:
303                     // something's gone wrong
304
throw new StreamCorruptedException JavaDoc(
305                         "Invalid primitive type. "
306                         + "Check version of beanutils used to serialize is compatible.");
307
308             }
309               
310         } else {
311             // it's another class
312
return ((Class JavaDoc) in.readObject());
313         }
314     }
315 }
Popular Tags