1 55 package org.lateralnz.common.util; 56 57 import java.io.File ; 58 import java.io.FileWriter ; 59 import java.io.FileInputStream ; 60 import java.io.InputStreamReader ; 61 import java.lang.reflect.Field ; 62 import java.sql.ResultSet ; 63 import java.sql.ResultSetMetaData ; 64 import java.sql.Types ; 65 import java.util.ArrayList ; 66 import java.util.Date ; 67 import java.util.HashMap ; 68 import java.util.List ; 69 70 76 public class ResultSetConverter implements Constants { 77 private static final Class [] DATE_CLASS_TYPE = { Date .class }; 78 private static final Class [] DOUBLE_CLASS_TYPE = { Double .class }; 79 private static final Class [] LONG_CLASS_TYPE = { Long .class }; 80 private static final Class [] STRING_CLASS_TYPE = { String .class }; 81 82 private static HashMap instances = new HashMap (); 83 84 private HashMap classes = new HashMap (); 85 private String compilerExecutable; 86 87 private static ResultSetConverter instance = null; 89 90 private ResultSetConverter(String compilerExecutable) { 91 setCompilerExecutable(compilerExecutable); 92 } 93 94 private void setCompilerExecutable(String compilerExecutable) { 95 this.compilerExecutable = compilerExecutable; 96 } 97 98 public static ResultSetConverter getInstance() throws Exception { 99 return getInstance("javac"); 100 } 101 102 105 public static ResultSetConverter getInstance(String compilerExecutable) throws Exception { 106 if (!instances.containsKey(compilerExecutable)) { 107 synchronized (instances) { 108 if (!instances.containsKey(compilerExecutable)) { 109 ResultSetConverter rsc = new ResultSetConverter(compilerExecutable); 110 instances.put(compilerExecutable, rsc); 111 } 112 } 113 } 114 115 return (ResultSetConverter)instances.get(compilerExecutable); 116 } 117 118 private final MetaClass getClassForResultSet(String resultName, ResultSet rs) throws Exception { 119 ResultSetMetaData md = rs.getMetaData(); 120 121 int count = md.getColumnCount(); 122 123 MetaClass metaclass = new MetaClass(count); 124 125 String [] getmethods = new String [count]; 126 String [] getomethods = new String [count]; 127 String [] setmethods = new String [count]; 128 String [] vars = new String [count]; 129 130 StringBuffer staticColnames = new StringBuffer ("public static String[] colnames = new String[]{ "); 131 132 for (int i = 0, j = 1; i < count; i++, j++) { 133 int type = md.getColumnType(j); 134 String colname = md.getColumnName(j); 135 staticColnames.append(QUOTE).append(colname).append(QUOTE); 136 if (i < count-1) { 137 staticColnames.append(COMMA); 138 } 139 if (colname.indexOf(SPACE) >= 0) { 140 colname = StringUtils.replace(colname, SPACE, UNDERSCORE); 141 } 142 colname = colname.substring(0,1).toUpperCase() + colname.substring(1); 143 switch (type) { 144 case Types.DECIMAL: 145 case Types.FLOAT: 146 case Types.DOUBLE: 147 metaclass.types[i] = MetaClass.DOUBLE; 148 vars[i] = "public double col" + j + ";"; 149 getmethods[i] = "public double get" + colname + "() { return this.col" + j + "; }"; 150 getomethods[i] = " new Double(col" + j +")"; 151 setmethods[i] = "public void set" + colname + "(double d) { this.col" + j + " = d; }"; 152 break; 153 case Types.INTEGER: 154 case Types.SMALLINT: 155 case Types.TINYINT: 156 metaclass.types[i] = MetaClass.LONG; 157 vars[i] = "public long col" + j + ";"; 158 getmethods[i] = "public long get" + colname + "() { return this.col" + j + "; }"; 159 getomethods[i] = " new Long(col" + j +")"; 160 setmethods[i] = "public void set" + colname + "(long l) { this.col" + j + " = l; }"; 161 break; 162 case Types.DATE: 163 case Types.TIME: 164 case Types.TIMESTAMP: 165 metaclass.types[i] = MetaClass.DATE; 166 vars[i] = "public Date col" + j + " = null;"; 167 getmethods[i] = "public Date get" + colname + "() { return this.col" + j + "; }"; 168 getomethods[i] = " col" + j; 169 setmethods[i] = "public void set" + colname + "(Date d) { this.col" + j + " = d; }"; 170 break; 171 case Types.VARCHAR: 172 case Types.CHAR: 173 default: 174 metaclass.types[i] = MetaClass.STRING; 175 vars[i] = "public String col" + j + " = null;"; 176 getmethods[i] = "public String get" + colname + "() { return this.col" + j + "; }"; 177 getomethods[i] = " col" + j; 178 setmethods[i] = "public void set" + colname + "(String s) { this.col" + j + " = s; }"; 179 break; 180 } 181 } 182 183 staticColnames.append("};\n\n"); 184 staticColnames.append("public static String getColName(int idx) { return colnames[idx]; }\n\n"); 185 staticColnames.append("public static int getColCount() { return colnames.length; }\n\n"); 186 187 StringBuffer sb = new StringBuffer ("import java.util.Date;\nimport java.util.Iterator;\nimport java.io.Serializable;\n\n"); 188 sb.append("public class ResultSetValue_" + resultName + " implements Iterator, Serializable {\n"); 189 sb.append(staticColnames.toString()).append(NEWLINE).append(NEWLINE); 190 sb.append("int pos = 0;\nint max = ").append(count).append(";\n\n"); 191 192 for (int i = 0; i < count; i++) { 193 sb.append(vars[i]).append(NEWLINE); 194 } 195 for (int i = 0; i < count; i++) { 196 sb.append(getmethods[i]).append(NEWLINE); 197 sb.append(setmethods[i]).append(NEWLINE); 198 } 199 sb.append("public boolean hasNext() { return (pos < max); }\n\n"); 200 sb.append("public Object next() {\ntry {\nswitch (pos) {\n"); 201 for (int i = 0; i < count; i++) { 202 sb.append("case ").append(i).append(": return ").append(getomethods[i]).append(";\n"); 203 } 204 sb.append("default: return null;\n}\n} finally { pos++; }\n}\npublic void remove() { }\n"); 205 206 if (count > 0) { 207 sb.append("\npublic String toString() {\nreturn \"\" + "); 208 for (int i = 1; i <= count; i++) { 209 sb.append("col").append(i); 210 if (i < count) { 211 sb.append(" + \",\" + "); 212 } 213 } 214 sb.append(";\n}\n"); 215 } 216 217 sb.append(NEWLINE).append("}"); 218 219 FileWriter fw = new FileWriter ("ResultSetValue_" + resultName + ".java"); 220 fw.write(sb.toString()); 221 222 fw.close(); 223 224 Process p = Runtime.getRuntime().exec(compilerExecutable + " ResultSetValue_" + resultName + ".java"); 225 p.waitFor(); 226 if (p.exitValue() != 0) { 227 InputStreamReader isr = null; 228 try { 229 isr = new InputStreamReader (p.getErrorStream()); 230 throw new Exception ("error compiling " + StringUtils.readFrom(isr)); 231 } 232 finally { 233 IOUtils.close(isr); 234 } 235 } 236 237 File f = new File ("ResultSetValue_" + resultName + ".class"); 238 FileInputStream fis = null; 239 byte[] b; 240 try { 241 fis = new FileInputStream (f); 242 b = new byte[(int)f.length()]; 243 fis.read(b); 244 } 245 finally { 246 IOUtils.close(fis); 247 } 248 249 InternalClassLoader icl = new InternalClassLoader(); 250 Class c = icl.getClass("ResultSetValue_" + resultName, b); 251 metaclass.c = c; 252 classes.put(resultName, metaclass); 253 254 return metaclass; 255 } 256 257 private final Field [] getFields(MetaClass mc) throws Exception { 258 Field [] f = new Field [mc.numOfFields]; 259 for (int i = 0, j = 1; i < f.length; i++, j++) { 260 f[i] = mc.c.getField("col" + j); 261 } 262 return f; 263 } 264 265 272 public List getResultSetAsList(String resultSetName, ResultSet rs, boolean forceClassReload) throws Exception { 273 MetaClass metaclass; 274 if (!classes.containsKey(resultSetName) || forceClassReload) { 275 metaclass = getClassForResultSet(resultSetName, rs); 276 } 277 else { 278 metaclass = (MetaClass)classes.get(resultSetName); 279 } 280 281 Field [] fields = getFields(metaclass); 282 Object [] val = new Object [1]; 283 ArrayList al = new ArrayList (); 284 while (rs.next()) { 285 Object valobj = metaclass.c.newInstance(); 286 287 for (int i = 0, j = 1; i < fields.length; i++, j++) { 288 switch (metaclass.types[i]) { 289 case MetaClass.DATE : 290 fields[i].set(valobj, rs.getTimestamp(j)); 291 break; 292 case MetaClass.DOUBLE : 293 fields[i].setDouble(valobj, rs.getDouble(j)); 294 break; 295 case MetaClass.LONG : 296 fields[i].setLong(valobj, rs.getLong(j)); 297 break; 298 default : 299 fields[i].set(valobj, rs.getString(j)); 300 break; 301 } 302 } 303 al.add(valobj); 304 } 305 306 return al; 307 } 308 309 public void reset(String name) { 310 classes.remove(name); 311 } 312 313 316 class InternalClassLoader extends ClassLoader { 317 public InternalClassLoader() { 318 super(); 319 } 320 321 public Class getClass(String name, byte[] b) { 322 return super.defineClass(name, b, 0, b.length); 323 } 324 } 325 326 class MetaClass { 327 public static final int STRING = 0; 328 public static final int LONG = 1; 329 public static final int DOUBLE = 2; 330 public static final int DATE = 3; 331 332 int numOfFields; 333 int[] types; 334 Class c; 335 336 public MetaClass(int numOfFields) { 337 this.numOfFields = numOfFields; 338 types = new int[numOfFields]; 339 } 340 } 341 } | Popular Tags |