1 /***
2 * License Agreement.
3 *
4 * JSPA (POJO-SP)
5 *
6 * Copyright (C) 2009 HRX Pty Ltd
7 *
8 * This file is part of JSPA.
9 *
10 * JSPA is free software: you can redistribute it and/or modify it under the
11 * terms of the GNU Lesser General Public License version 3 as published by the
12 * Free Software Foundation.
13 *
14 * JSPA is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with JSPA. If not, see <http://www.gnu.org/licenses/>.
20 */
21 package com.hrx.rasp.util.dao;
22
23 import java.io.Reader;
24 import java.lang.reflect.Field;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Modifier;
27 import java.math.BigDecimal;
28 import java.math.BigInteger;
29 import java.sql.Array;
30 import java.sql.CallableStatement;
31 import java.sql.Clob;
32 import java.sql.ResultSet;
33 import java.sql.ResultSetMetaData;
34 import java.sql.SQLException;
35 import java.sql.Struct;
36 import java.sql.Timestamp;
37 import java.sql.Types;
38 import java.util.Arrays;
39 import java.util.Calendar;
40 import java.util.Collection;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44
45 import org.apache.log4j.Logger;
46
47 import com.hrx.rasp.util.dao.exception.FieldNotFoundException;
48 import com.hrx.rasp.util.dao.exception.InvalidFieldException;
49 import com.hrx.rasp.util.dao.exception.StoredProcedurePrepareException;
50
51 /***
52 * @author dan.stoica <dan.stoica@acslink.net.au>
53 *
54 */
55 public class StoredProcUtility
56 {
57 private static Logger log = Logger.getLogger(StoredProcUtility.class);
58
59 private static String[] PASSWD_KEY_WORDS =
60 {
61 "PASSWD", "", "PASSWORD"
62 };
63
64 static
65 {
66 Arrays.sort(PASSWD_KEY_WORDS);
67 }
68
69 /***
70 * Returns a String which capitalizes the first letter of the string.
71 */
72 public static String capitalize(String propertyName)
73 {
74 if (propertyName == null || propertyName.length() == 0)
75 {
76 return propertyName;
77 }
78 return propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
79 }
80
81 public static Map<String, Method> createMethodMapIN(Object dao)
82 {
83 Map<String, Method> methodMap = new HashMap<String, Method>(dao.getClass().getMethods().length + 2);
84 Method[] methods = dao.getClass().getMethods();
85 String methodName = "";
86
87 for (int i = 0; i < methods.length; i++)
88 {
89 methodName = methods[i].getName();
90
91 if (methodName.startsWith("set") && (methods[i].getParameterTypes().length == 1))
92 {
93 methodMap.put(methods[i].getName(), methods[i]);
94 }
95 }
96 return methodMap;
97 }
98
99 public static Map<String, Method> createMethodMapOUT(Object dao)
100 {
101 Map<String, Method> methodMap = new HashMap<String, Method>(dao.getClass().getMethods().length + 2);
102 Method[] methods = dao.getClass().getMethods();
103 String methodName = "";
104
105 for (int i = 0; i < methods.length; i++)
106 {
107 methodName = methods[i].getName();
108
109 if (methodName.startsWith("get") && (methods[i].getParameterTypes().length == 0))
110 {
111 methodMap.put(methods[i].getName(), methods[i]);
112 }
113 }
114 return methodMap;
115 }
116
117 public static Class<?> getFieldType(Object dao, String fieldName) throws StoredProcedurePrepareException
118 {
119 try
120 {
121 Class<?> cls = (Class<?>) dao.getClass();
122
123 Field f = getField(cls, fieldName);
124 return f.getType();
125 }
126 catch (Exception e)
127 {
128 throw new StoredProcedurePrepareException("Failed to get field type from dao (" + fieldName + ")", e);
129 }
130
131 }
132
133 /***
134 * Return TRUE if the modifier is not transient, abstract or static
135 */
136 public static boolean isValidPersistenceField(int modifier)
137 {
138 return !(Modifier.isTransient(modifier) || Modifier.isAbstract(modifier) || Modifier.isStatic(modifier));
139 }
140
141 /***
142 * Throws an InvalidFieldException if the field is transient, abstract or
143 * static
144 *
145 * @param field
146 * @throws InvalidFieldException
147 */
148 public static void validateField(Field field) throws InvalidFieldException
149 {
150 if (!StoredProcUtility.isValidPersistenceField(field.getModifiers()))
151 {
152 throw new InvalidFieldException(field.getName());
153 }
154 }
155
156 /***
157 * Simple method for finding the SQL type for a given java Object.
158 *
159 * @param java
160 * Object
161 *
162 * @return int
163 */
164 public static int getSQLType(Object javaObject)
165 {
166 return getSQLType(javaObject.getClass());
167 }
168
169 /***
170 * short method for getting the sql type for a given class.
171 *
172 * @param javaType
173 * Class
174 * @return int
175 */
176 public static int getSQLType(Class<?> javaType)
177 {
178 if (javaType == String.class)
179 return Types.VARCHAR;
180 else if (javaType == BigDecimal.class)
181 return Types.DECIMAL;
182 else if (javaType == BigInteger.class)
183 return Types.BIGINT;
184 else if (javaType == Byte.class || javaType == byte.class)
185 return Types.TINYINT;
186 else if (javaType == Character.class || javaType == char.class)
187 return Types.CHAR;
188 else if (javaType == Double.class || javaType == double.class)
189 return Types.DOUBLE;
190 else if (javaType == Float.class || javaType == float.class)
191 return Types.FLOAT;
192 else if (javaType == Long.class || javaType == long.class)
193 return Types.BIGINT;
194 else if (javaType == Boolean.class || javaType == boolean.class)
195 return Types.BIT;
196 else if (javaType == Integer.class || javaType == int.class)
197 return Types.INTEGER;
198 else if (javaType == Number.class)
199 return Types.DECIMAL;
200 else if (javaType == Short.class || javaType == short.class)
201 return Types.SMALLINT;
202 else if (javaType == java.util.Date.class || javaType == java.sql.Timestamp.class)
203 return Types.TIMESTAMP;
204 else if (javaType == java.util.Calendar.class)
205 return Types.TIMESTAMP;
206 else if (javaType == java.sql.Time.class)
207 return Types.TIME;
208 else if (javaType == java.sql.Date.class)
209 return Types.DATE;
210 else if (javaType == Byte[].class || javaType == byte[].class)
211 return Types.LONGVARBINARY;
212 else if (javaType == java.sql.Blob.class)
213 return Types.BLOB;
214 else if (javaType == char[].class || javaType == Character[].class)
215 return Types.LONGVARCHAR;
216 else if (javaType == Clob.class)
217 return Types.CLOB;
218 else if (javaType == Struct.class)
219 return Types.STRUCT;
220 else if (javaType.isArray())
221 return Types.ARRAY;
222 else if (javaType == Collection.class || javaType == List.class)
223 {
224 return OracleHelper.ORACLE_CURSOR;
225 }
226 else
227 return Types.OTHER;
228 }
229
230 private static Field getField(Class<?> cls, String name) throws FieldNotFoundException
231 {
232 if (cls == null)
233 {
234 throw new FieldNotFoundException("Field not found: " + name);
235 }
236 Field field;
237 try
238 {
239 field = cls.getDeclaredField(name);
240 }
241 catch (NoSuchFieldException nsfe)
242 {
243 Class<?> clsSupper = cls.getSuperclass();
244 field = getField(clsSupper, name);
245 }
246 if (!Modifier.isPublic(field.getModifiers()))
247 {
248 field.setAccessible(true);
249 }
250 return field;
251 }
252
253 public static Object getCallableStatementObject(final CallableStatement stmt, final int index, final Class<?> objectType) throws SQLException
254 {
255 Object result = null;
256
257 if (objectType == String.class)
258 {
259 result = stmt.getString(index);
260 }
261 else if (objectType == Integer.class)
262 {
263 final int value = stmt.getInt(index);
264 result = stmt.wasNull() ? null : new Integer(value);
265 }
266 else if (objectType == Integer.TYPE)
267 {
268 result = stmt.getInt(index);
269 }
270 else if (objectType == Long.class)
271 {
272 final long value = stmt.getLong(index);
273 result = stmt.wasNull() ? null : new Long(value);
274 }
275 else if (objectType == Long.TYPE)
276 {
277 result = stmt.getLong(index);
278 }
279 else if (objectType == Double.class)
280 {
281 final double value = stmt.getDouble(index);
282 result = stmt.wasNull() ? null : new Double(value);
283 }
284 else if (objectType == Double.TYPE)
285 {
286 result = stmt.getDouble(index);
287 }
288 else if (objectType == Float.class)
289 {
290 final float value = stmt.getFloat(index);
291 result = stmt.wasNull() ? null : new Float(value);
292 }
293 else if (objectType == Float.TYPE)
294 {
295 result = stmt.getFloat(index);
296 }
297 else if (objectType == Short.class)
298 {
299 final short value = stmt.getShort(index);
300 result = stmt.wasNull() ? null : new Short(value);
301 }
302 else if (objectType == Short.TYPE)
303 {
304 result = stmt.getShort(index);
305 }
306 else if (objectType == Boolean.class)
307 {
308 final boolean value = stmt.getBoolean(index);
309 result = stmt.wasNull() ? null : new Boolean(value);
310 }
311 else if (objectType == Boolean.TYPE)
312 {
313 result = stmt.getBoolean(index);
314 }
315 else if (objectType == Timestamp.class)
316 {
317 result = stmt.getTimestamp(index);
318 }
319 else if (objectType == java.util.Date.class)
320 {
321 result = stmt.getTimestamp(index);
322 }
323 else if (objectType == java.util.Calendar.class)
324 {
325 Timestamp date = stmt.getTimestamp(index);
326 if (date != null)
327 {
328 result = Calendar.getInstance();
329 ((Calendar) result).setTime(date);
330 }
331 }
332 else if (objectType == java.sql.Date.class)
333 {
334 result = stmt.getDate(index);
335 }
336 else if (objectType == java.sql.Time.class)
337 {
338 result = stmt.getTime(index);
339 }
340 else if (objectType == Clob.class)
341 {
342 result = stmt.getClob(index);
343 }
344 else if (objectType.isArray())
345 {
346 Array rsArr = stmt.getArray(index);
347 result = stmt.wasNull() ? null : rsArr.getArray();
348 }
349 else if (objectType == Reader.class)
350 {
351 result = stmt.getCharacterStream(index);
352 }
353 else
354 {
355 result = stmt.getObject(index);
356 }
357 return result;
358
359 }
360
361 public static Object getResultSetObject(final ResultSet rs, final int index, final Class<?> objectType) throws SQLException
362 {
363 Object result = null;
364
365 if (objectType == String.class)
366 {
367 result = rs.getString(index);
368 }
369 else if (objectType == Integer.class)
370 {
371 final int value = rs.getInt(index);
372 result = rs.wasNull() ? null : new Integer(value);
373 }
374 else if (objectType == Integer.TYPE)
375 {
376 result = rs.getInt(index);
377 }
378 else if (objectType == Long.class)
379 {
380 final long value = rs.getLong(index);
381 result = rs.wasNull() ? null : new Long(value);
382 }
383 else if (objectType == Long.TYPE)
384 {
385 result = rs.getLong(index);
386 }
387 else if (objectType == Double.class)
388 {
389 final double value = rs.getDouble(index);
390 result = rs.wasNull() ? null : new Double(value);
391 }
392 else if (objectType == Double.TYPE)
393 {
394 result = rs.getDouble(index);
395 }
396 else if (objectType == Float.class)
397 {
398 final float value = rs.getFloat(index);
399 result = rs.wasNull() ? null : new Float(value);
400 }
401 else if (objectType == Float.TYPE)
402 {
403 result = rs.getFloat(index);
404 }
405 else if (objectType == Short.class)
406 {
407 final short value = rs.getShort(index);
408 result = rs.wasNull() ? null : new Short(value);
409 }
410 else if (objectType == Short.TYPE)
411 {
412 result = rs.getShort(index);
413 }
414 else if (objectType == Boolean.class)
415 {
416 final boolean value = rs.getBoolean(index);
417 result = rs.wasNull() ? null : new Boolean(value);
418 }
419 else if (objectType == Boolean.TYPE)
420 {
421 result = rs.getBoolean(index);
422 }
423 else if (objectType == Timestamp.class)
424 {
425 result = rs.getTimestamp(index);
426 }
427 else if (objectType == java.util.Date.class)
428 {
429 result = rs.getTimestamp(index);
430 }
431 else if (objectType == java.util.Calendar.class)
432 {
433 Timestamp date = rs.getTimestamp(index);
434 if (date != null)
435 {
436 result = Calendar.getInstance();
437 ((Calendar) result).setTime(date);
438 }
439 }
440 else if (objectType == java.sql.Date.class)
441 {
442 result = rs.getDate(index);
443 }
444 else if (objectType == java.sql.Time.class)
445 {
446 result = rs.getTime(index);
447 }
448 else if (objectType == Clob.class)
449 {
450 result = rs.getClob(index);
451 }
452 else if (objectType.isArray())
453 {
454 Array rsArr = rs.getArray(index);
455 result = rs.wasNull() ? null : rsArr.getArray();
456 }
457 else if (objectType == Reader.class)
458 {
459 result = rs.getCharacterStream(index);
460 }
461 else
462 {
463 result = rs.getObject(index);
464 }
465 return result;
466 }
467
468 /***
469 * convenience method for debugging, logs the contents of the current record
470 * of a ResultSet
471 *
472 * @param resultSet
473 * ResultSet
474 */
475 public static void dumpResultSetRecord(final ResultSet resultSet)
476 {
477 dumpResultSetRecord(log, resultSet);
478 }
479
480 /***
481 * Convenience debugging method used to logs the content of the current
482 * record of a ResultSet
483 *
484 * @param resultSet
485 * ResultSet
486 */
487 public static void dumpResultSetRecord(final Logger log, final ResultSet resultSet)
488 {
489 if (log.isTraceEnabled())
490 {
491 try
492 {
493 ResultSetMetaData metaData = resultSet.getMetaData();
494 int columnCount = metaData.getColumnCount();
495 log.trace("DAO: Start dumping ResultSet: " + columnCount + " columns");
496
497 for (int i = 1; i <= columnCount; i++)
498 {
499 Object value = resultSet.getObject(i);
500 String colName = metaData.getColumnName(i).toUpperCase();
501
502 if (Arrays.binarySearch(PASSWD_KEY_WORDS, colName) > 0)
503 {
504 value = "********";
505 }
506 log.trace("DAO: Column " + i + ": " + colName + " value:" + value + " type" + metaData.getColumnType(i));
507 }
508 }
509 catch (SQLException exc)
510 {
511 log.error("DAO: Error dumping result set.");
512 }
513 }
514 }
515
516 public static double duration(long startTime)
517 {
518 double time = System.currentTimeMillis() - startTime;
519 time = time / 1000;
520 return time;
521 }
522 }