View Javadoc
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 					// hide the sensitive informations like passwords
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 }