1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.beanutils;
18
19 import java.io.Serializable;
20 import java.sql.ResultSet;
21 import java.sql.ResultSetMetaData;
22 import java.sql.SQLException;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 /**
28 * <p>Provides common logic for JDBC implementations of {@link DynaClass}.</p>
29 *
30 * @author Craig R. McClanahan
31 * @author George Franciscus
32 * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:33 $
33 */
34
35 abstract class JDBCDynaClass implements DynaClass, Serializable {
36
37
38
39 /**
40 * <p>Flag defining whether column names should be lower cased when
41 * converted to property names.</p>
42 */
43 protected boolean lowerCase = true;
44
45 /**
46 * <p>The set of dynamic properties that are part of this
47 * {@link DynaClass}.</p>
48 */
49 protected DynaProperty properties[] = null;
50
51 /**
52 * <p>The set of dynamic properties that are part of this
53 * {@link DynaClass}, keyed by the property name. Individual descriptor
54 * instances will be the same instances as those in the
55 * <code>properties</code> list.</p>
56 */
57 protected Map propertiesMap = new HashMap();
58
59
60
61 /**
62 * <p>Return the name of this DynaClass (analogous to the
63 * <code>getName()</code> method of <code>java.lang.Class</code), which
64 * allows the same <code>DynaClass</code> implementation class to support
65 * different dynamic classes, with different sets of properties.</p>
66 */
67 public String getName() {
68
69 return (this.getClass().getName());
70
71 }
72
73 /**
74 * <p>Return a property descriptor for the specified property, if it
75 * exists; otherwise, return <code>null</code>.</p>
76 *
77 * @param name Name of the dynamic property for which a descriptor
78 * is requested
79 *
80 * @exception IllegalArgumentException if no property name is specified
81 */
82 public DynaProperty getDynaProperty(String name) {
83
84 if (name == null) {
85 throw new IllegalArgumentException("No property name specified");
86 }
87 return ((DynaProperty) propertiesMap.get(name));
88
89 }
90
91 /**
92 * <p>Return an array of <code>ProperyDescriptors</code> for the properties
93 * currently defined in this DynaClass. If no properties are defined, a
94 * zero-length array will be returned.</p>
95 */
96 public DynaProperty[] getDynaProperties() {
97
98 return (properties);
99
100 }
101
102 /**
103 * <p>Instantiate and return a new DynaBean instance, associated
104 * with this DynaClass. <strong>NOTE</strong> - This operation is not
105 * supported, and throws an exception.</p>
106 *
107 * @exception IllegalAccessException if the Class or the appropriate
108 * constructor is not accessible
109 * @exception InstantiationException if this Class represents an abstract
110 * class, an array class, a primitive type, or void; or if instantiation
111 * fails for some other reason
112 */
113 public DynaBean newInstance()
114 throws IllegalAccessException, InstantiationException {
115
116 throw new UnsupportedOperationException("newInstance() not supported");
117
118 }
119
120 /**
121 * <p>Loads and returns the <code>Class</code> of the given name.
122 * By default, a load from the thread context class loader is attempted.
123 * If there is no such class loader, the class loader used to load this
124 * class will be utilized.</p>
125 *
126 * @exception SQLException if an exception was thrown trying to load
127 * the specified class
128 */
129 protected Class loadClass(String className) throws SQLException {
130
131 try {
132 ClassLoader cl = Thread.currentThread().getContextClassLoader();
133 if (cl == null) {
134 cl = this.getClass().getClassLoader();
135 }
136 return (cl.loadClass(className));
137 } catch (Exception e) {
138 throw new SQLException(
139 "Cannot load column class '" + className + "': " + e);
140 }
141
142 }
143
144 /**
145 * <p>Factory method to create a new DynaProperty for the given index
146 * into the result set metadata.</p>
147 *
148 * @param metadata is the result set metadata
149 * @param i is the column index in the metadata
150 * @return the newly created DynaProperty instance
151 */
152 protected DynaProperty createDynaProperty(
153 ResultSetMetaData metadata,
154 int i)
155 throws SQLException {
156
157 String name = null;
158 if (lowerCase) {
159 name = metadata.getColumnName(i).toLowerCase();
160 } else {
161 name = metadata.getColumnName(i);
162 }
163 String className = null;
164 try {
165 className = metadata.getColumnClassName(i);
166 } catch (SQLException e) {
167
168
169 }
170
171
172
173 Class clazz = Object.class;
174 if (className != null) {
175 clazz = loadClass(className);
176 }
177 return new DynaProperty(name, clazz);
178
179 }
180
181 /**
182 * <p>Introspect the metadata associated with our result set, and populate
183 * the <code>properties</code> and <code>propertiesMap</code> instance
184 * variables.</p>
185 *
186 * @param resultSet The <code>resultSet</code> whose metadata is to
187 * be introspected
188 *
189 * @exception SQLException if an error is encountered processing the
190 * result set metadata
191 */
192 protected void introspect(ResultSet resultSet) throws SQLException {
193
194
195 ArrayList list = new ArrayList();
196 ResultSetMetaData metadata = resultSet.getMetaData();
197 int n = metadata.getColumnCount();
198 for (int i = 1; i <= n; i++) {
199 DynaProperty dynaProperty = createDynaProperty(metadata, i);
200 if (dynaProperty != null) {
201 list.add(dynaProperty);
202 }
203 }
204
205
206 properties =
207 (DynaProperty[]) list.toArray(new DynaProperty[list.size()]);
208 for (int i = 0; i < properties.length; i++) {
209 propertiesMap.put(properties[i].getName(), properties[i]);
210 }
211
212 }
213
214 }