View Javadoc

1   /*
2    * $Header: /cvsroot/valuelist/valuelist/src/java/net/mlw/vlh/adapter/jdbc/dynabean/fix/JDBCDynaClass.java,v 1.2 2005/08/19 16:06:29 smarek Exp $
3    * $Revision: 1.2 $
4    * $Date: 2005/08/19 16:06:29 $
5    *
6    * ====================================================================
7    * 
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer. 
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution,
26   *    if any, must include the following acknowledgement:  
27   *       "This product includes software developed by the 
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowledgement may appear in the software itself,
30   *    if and wherever such third-party acknowledgements normally appear.
31   *
32   * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software
33   *    Foundation" must not be used to endorse or promote products derived
34   *    from this software without prior written permission. For written 
35   *    permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache",
38   *    "Apache" nor may "Apache" appear in their names without prior 
39   *    written permission of the Apache Software Foundation.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   *
60   */ 
61  
62  package net.mlw.vlh.adapter.jdbc.dynabean.fix;
63  
64  import java.io.Serializable;
65  import java.sql.ResultSet;
66  import java.sql.ResultSetMetaData;
67  import java.sql.SQLException;
68  import java.util.ArrayList;
69  import java.util.HashMap;
70  import java.util.List;
71  import java.util.Map;
72  
73  import org.apache.commons.beanutils.DynaBean;
74  import org.apache.commons.beanutils.DynaClass;
75  import org.apache.commons.beanutils.DynaProperty;
76  
77  /***
78   * <p>Provides common logic for JDBC implementations of {@link DynaClass}.</p>
79   *
80   * @author   Craig R. McClanahan
81   * @author   George Franciscus
82   * @version $Revision: 1.2 $ $Date: 2005/08/19 16:06:29 $
83   */
84  
85  abstract class JDBCDynaClass implements DynaClass, Serializable {
86  
87      // ----------------------------------------------------- Instance Variables
88  
89      /***
90       * <p>Flag defining whether column names should be lower cased when
91       * converted to property names.</p>
92       */
93      protected boolean lowerCase = true;
94  
95  	/***
96  	 * <p>Flag defining whether column names should be the column name
97  	 * or the column label.</p>
98  	 */
99  	 protected boolean useName = true;
100 		 
101 		 
102     /***
103      * <p>The set of dynamic properties that are part of this
104      * {@link DynaClass}.</p>
105      */
106     protected DynaProperty properties[] = null;
107 
108     /***
109      * <p>The set of dynamic properties that are part of this
110      * {@link DynaClass}, keyed by the property name.  Individual descriptor
111      * instances will be the same instances as those in the
112      * <code>properties</code> list.</p>
113      */
114     protected Map propertiesMap = new HashMap();
115 
116     // ------------------------------------------------------ DynaClass Methods
117 
118     /***
119      * <p>Return the name of this DynaClass (analogous to the
120      * <code>getName()</code> method of <code>java.lang.Class</code), which
121      * allows the same <code>DynaClass</code> implementation class to support
122      * different dynamic classes, with different sets of properties.</p>
123      */
124     public String getName() {
125 
126         return (this.getClass().getName());
127 
128     }
129 
130     /***
131      * <p>Return a property descriptor for the specified property, if it
132      * exists; otherwise, return <code>null</code>.</p>
133      *
134      * @param name Name of the dynamic property for which a descriptor
135      *  is requested
136      *
137      * @exception IllegalArgumentException if no property name is specified
138      */
139     public DynaProperty getDynaProperty(String name) {
140 
141         if (name == null) {
142             throw new IllegalArgumentException("No property name specified");
143         }
144         return ((DynaProperty) propertiesMap.get(name));
145 
146     }
147 
148     /***
149      * <p>Return an array of <code>ProperyDescriptors</code> for the properties
150      * currently defined in this DynaClass.  If no properties are defined, a
151      * zero-length array will be returned.</p>
152      */
153     public DynaProperty[] getDynaProperties() {
154 
155         return (properties);
156 
157     }
158 
159     /***
160      * <p>Instantiate and return a new DynaBean instance, associated
161      * with this DynaClass.  <strong>NOTE</strong> - This operation is not
162      * supported, and throws an exception.</p>
163      *
164      * @exception IllegalAccessException if the Class or the appropriate
165      *  constructor is not accessible
166      * @exception InstantiationException if this Class represents an abstract
167      *  class, an array class, a primitive type, or void; or if instantiation
168      *  fails for some other reason
169      */
170     public DynaBean newInstance()
171             throws IllegalAccessException, InstantiationException {
172 
173         throw new UnsupportedOperationException("newInstance() not supported");
174 
175     }
176 
177     /***
178      * <p>Loads and returns the <code>Class</code> of the given name.
179      * By default, a load from the thread context class loader is attempted.
180      * If there is no such class loader, the class loader used to load this
181      * class will be utilized.</p>
182      *
183      * @exception SQLException if an exception was thrown trying to load
184      *  the specified class
185      */
186     protected Class loadClass(String className) throws SQLException {
187 
188         try {
189             ClassLoader cl = Thread.currentThread().getContextClassLoader();
190             if (cl == null) {
191                     cl = this.getClass().getClassLoader();
192             }
193             return (cl.loadClass(className));
194         } catch (Exception e) {
195             throw new SQLException(
196                     "Cannot load column class '" + className + "': " + e);
197         }
198 
199     }
200 
201     /***
202      * <p>Factory method to create a new DynaProperty for the given index
203      * into the result set metadata.</p>
204      * 
205      * @param metadata is the result set metadata
206      * @param i is the column index in the metadata
207      * @return the newly created DynaProperty instance
208      */
209     protected DynaProperty createDynaProperty(
210                                     ResultSetMetaData metadata,
211                                     int i)
212                                     throws SQLException {
213 
214         String name = ( useName ) ? metadata.getColumnName(i) : metadata.getColumnLabel(i);
215 						  
216         if (lowerCase) {
217         	   name = name.toLowerCase();
218         }
219 
220         String className = null;
221         try {
222             className = metadata.getColumnClassName(i);
223         } catch (SQLException e) {
224             // this is a patch for HsqlDb to ignore exceptions
225             // thrown by its metadata implementation
226         }
227 
228         // Default to Object type if no class name could be retrieved
229         // from the metadata
230         Class clazz = Object.class;
231         if (className != null) {
232             clazz = loadClass(className);
233         }
234         return new DynaProperty(name, clazz);
235 
236     }
237 
238     /***
239      * <p>Introspect the metadata associated with our result set, and populate
240      * the <code>properties</code> and <code>propertiesMap</code> instance
241      * variables.</p>
242      *
243      * @param resultSet The <code>resultSet</code> whose metadata is to
244      *  be introspected
245      *
246      * @exception SQLException if an error is encountered processing the
247      *  result set metadata
248      */
249     protected void introspect(ResultSet resultSet) throws SQLException {
250 
251         // Accumulate an ordered list of DynaProperties
252         List list = new ArrayList();
253         ResultSetMetaData metadata = resultSet.getMetaData();
254         int n = metadata.getColumnCount();
255         for (int i = 1; i <= n; i++) { // JDBC is one-relative!
256             DynaProperty dynaProperty = createDynaProperty(metadata, i);
257             if (dynaProperty != null) {
258                     list.add(dynaProperty);
259             }
260         }
261 
262         // Convert this list into the internal data structures we need
263         properties =
264             (DynaProperty[]) list.toArray(new DynaProperty[list.size()]);
265         for (int i = 0; i < properties.length; i++) {
266             propertiesMap.put(properties[i].getName(), properties[i]);
267         }
268 
269     }
270 
271 }