| 1 64 package com.jcorporate.expresso.core.db; 65 66 import com.jcorporate.expresso.core.db.config.TypeMappingConfig; 67 import com.jcorporate.expresso.core.dbobj.DBField; 68 import com.jcorporate.expresso.core.misc.ConfigContext; 69 import com.jcorporate.expresso.core.misc.ConfigManager; 70 import com.jcorporate.expresso.core.misc.StringUtil; 71 import com.jcorporate.expresso.kernel.ComponentLifecycle; 72 import com.jcorporate.expresso.kernel.Configuration; 73 import com.jcorporate.expresso.kernel.exception.ConfigurationException; 74 import com.jcorporate.expresso.kernel.util.LocatorUtils; 75 import org.apache.log4j.Logger; 76 77 import java.util.Enumeration ; 78 import java.util.HashMap ; 79 import java.util.Hashtable ; 80 import java.util.Iterator ; 81 import java.util.Map ; 82 83 84 92 public class TypeMapper extends com.jcorporate.expresso.kernel.EmbeddedComponent 93 implements ComponentLifecycle { 94 97 private static Logger log = Logger.getLogger(TypeMapper.class); 98 99 103 private static Map mapInstances = new HashMap (); 104 105 108 private Map expressoFromSQL = new HashMap (30); 109 110 113 private Map expressoToJava = new HashMap (30); 114 115 118 private Map expressoToSQL = new HashMap (30); 119 120 123 private Map sqlToDB = new HashMap (30); 124 125 128 private Map sqlTypeNames = new HashMap (30); 129 130 133 private Map typeToString = new HashMap (30); 134 135 138 private String dataContext = null; 139 140 143 private boolean componentConfiguration = false; 144 145 148 public TypeMapper() { 149 } 150 151 156 protected TypeMapper(String thedataContext) { 157 this.dataContext = thedataContext; 158 } 159 160 167 public Integer getExpressoToJava(String dbFieldType) { 168 return (Integer ) expressoToJava.get(dbFieldType); 169 } 170 171 176 public Map getExpressoToSQLMap() { 177 return expressoToSQL; 178 } 179 180 181 193 public static synchronized TypeMapper getInstance(String dataContext) 194 throws DBException { 195 if (dataContext == null) { 196 throw new IllegalArgumentException ("Parameter data context cannot be null"); 197 } 198 199 TypeMapper theInstance = (TypeMapper) mapInstances.get(dataContext); 200 201 synchronized (TypeMapper.class) { 202 if (theInstance == null) { 203 theInstance = new TypeMapper(); 204 theInstance.dataContext = dataContext; 205 theInstance.initializeTypes(dataContext); 206 mapInstances.put(dataContext, theInstance); 207 } 208 } 209 210 return theInstance; 211 } 212 213 222 public int getJavaSQLType(String fieldType) throws DBException { 223 Integer i = (Integer ) expressoToJava.get(fieldType); 224 225 if (i == null) { 226 throw new DBException("Unable to locate java.sql.Types mapping for field type: " + 227 fieldType); 228 } 229 230 return i.intValue(); 231 } 232 233 241 public String getMetadataName() { 242 return "TypeMapper"; 243 } 244 245 251 public String getNameForSQL(int sqlType) { 252 return (String ) sqlTypeNames.get(new Integer (sqlType)); 253 } 254 255 260 public Map getSQLToDBMap() { 261 return sqlToDB; 262 } 263 264 265 274 public String getTypeForDB(String expressoType) throws DBException { 275 276 String sqlType = (String ) expressoToSQL.get(expressoType); 277 278 if (sqlType == null) { 279 throw new DBException("There was no mapping of types from the" + 280 " expresso type '" + expressoType + 281 "' to a java.sql.Types String " + 282 "type - perhaps there should be a type mapping " + 283 "entry in expresso-config.xml?"); 284 } 285 286 287 String dbType = (String ) sqlToDB.get(sqlType); 288 289 if (dbType == null) { 290 Integer javaIntType = (Integer ) expressoToJava.get(sqlType.toLowerCase()); 291 292 if (javaIntType == null) { 293 throw new DBException("There was no mapping of types from the" + 294 " expresso type '" + expressoType + 295 "' to a java.sql.Types " + 296 "type integer - perhaps there should be a type mapping " + 297 "entry in expresso-config.xml?"); 298 } 299 300 dbType = (String ) sqlToDB.get(javaIntType); 301 302 if (dbType == null) { 303 throw new DBException("There was no mapping of the java.sql.Type." + sqlType + 304 " type to a specific database type. Either this " + 305 "type is not supported by the specified JDBC driver, or " + 306 "there should be an type mapping entry in " + 307 "expresso-config.xml"); 308 } 309 } 310 311 return dbType; 312 } 313 314 315 322 public String getTypeForExpresso(int sqlType) throws DBException { 323 324 Integer sqlInt = new Integer (sqlType); 325 String sqlStr = (String ) typeToString.get(sqlInt); 326 327 if (sqlStr == null) { 328 throw new DBException("There was no mapping for type " + sqlType + 329 " to a string type "); 330 } 331 332 String expressoType = (String ) expressoFromSQL.get(sqlStr.toLowerCase()); 333 334 if (expressoType == null) { 335 throw new DBException("There was no mapping of types from the" + 336 " sql type '" + sqlStr + "' to a expresso Type "); 337 } 338 339 return expressoType; 340 } 341 342 343 349 public String getTypeForSQL(int sqlType) { 350 return (String ) typeToString.get(new Integer (sqlType)); 351 } 352 353 359 public synchronized void configure(Configuration newConfig) 360 throws ConfigurationException { 361 synchronized (TypeMapper.class) { 362 LocatorUtils lc = new LocatorUtils(this); 363 dataContext = lc.getDataContextName(this); 364 365 try { 366 if (dataContext != null) { 367 this.initializeTypes(dataContext); 368 mapInstances.put(dataContext, this); 369 } else { 370 throw new ConfigurationException("Unable to find parent data context!"); 371 } 372 } catch (DBException ex) { 373 log.error("Error configuring TypeMapper", ex); 374 throw new ConfigurationException("Error Configuring TypeMapper", 375 ex); 376 } catch (Throwable t) { 377 log.error("Error configuring TypeMapper", t); 378 throw new ConfigurationException("Error Configuring TypeMapper", 379 t); 380 } 381 } 382 } 383 384 388 public void destroy() { 389 synchronized (TypeMapper.class) { 390 if (mapInstances != null) { 391 mapInstances.remove(dataContext); 392 expressoToSQL = null; 393 } 394 395 expressoToSQL = null; 396 expressoFromSQL = null; 397 sqlToDB = null; 398 typeToString = null; 399 expressoToJava = null; 400 sqlTypeNames = null; 401 } 402 } 403 404 407 public void initialize() { 408 componentConfiguration = true; 409 } 410 411 418 public synchronized void reconfigure(Configuration newConfig) 419 throws ConfigurationException { 420 synchronized (TypeMapper.class) { 421 LocatorUtils lc = new LocatorUtils(this); 422 dataContext = lc.getDataContextName(this); 423 mapInstances.remove(dataContext); 424 425 try { 426 expressoToSQL = new HashMap (30); 427 expressoFromSQL = new HashMap (30); 428 sqlToDB = new HashMap (30); 429 typeToString = new HashMap (30); 430 expressoToJava = new HashMap (30); 431 sqlTypeNames = new HashMap (30); 432 this.initializeTypes(dataContext); 433 } catch (DBException ex) { 434 throw new ConfigurationException("Error Configuring TypeMapper", 435 ex); 436 } 437 438 mapInstances.put(dataContext, this); 439 } 440 } 441 442 449 protected void initializeTypes(String dataContext) 450 throws DBException { 451 if (log.isInfoEnabled()) { 452 log.info("Initializing Type Mapping for context: " + dataContext); 453 } 454 455 456 buildTypeToString(); 457 buildSqlTypeNames(); 458 buildExpressoToSQL(); 459 460 463 for (Iterator i = expressoToSQL.keySet().iterator(); i.hasNext();) { 464 String oneKey = (String ) i.next(); 465 String oneValue = (String ) expressoToSQL.get(oneKey); 466 expressoFromSQL.put(oneValue.toLowerCase(), oneKey); 467 } 468 469 472 DBConnection myConnection = null; 473 DBConnectionPool myPool = null; 474 475 buildSqlToDB(); 476 477 for (Iterator i = typeToString.keySet().iterator(); i.hasNext();) { 482 Integer aKey = (Integer ) i.next(); 483 String aValue = (String ) typeToString.get(aKey); 484 expressoToJava.put(aValue.toLowerCase(), aKey); 485 } 486 487 expressoToJava.put(DBField.INTEGER_TYPE, 489 new Integer (java.sql.Types.INTEGER)); 490 expressoToJava.put(DBField.BOOLEAN_TYPE, new Integer (java.sql.Types.BIT)); 491 expressoToJava.put(DBField.LONG_TYPE, new Integer (java.sql.Types.BIGINT)); 492 expressoToJava.put(DBField.DATETIME_TYPE, 493 new Integer (java.sql.Types.TIMESTAMP)); 494 expressoToJava.put(DBField.TEXT_TYPE, 495 new Integer (java.sql.Types.LONGVARCHAR)); 496 expressoToJava.put(DBField.AUTOINC_TYPE, 497 new Integer (java.sql.Types.INTEGER)); 498 499 try { 500 myPool = DBConnectionPool.getInstance(dataContext); 501 myConnection = myPool.getConnection("Schema"); 502 503 504 505 Hashtable dbMap = myConnection.getTypeMap(); 506 myPool.release(myConnection); 507 508 Integer oneIntValue = null; 509 510 for (Enumeration ex = dbMap.keys(); ex.hasMoreElements();) { 511 String oneKey = (String ) ex.nextElement(); 512 oneIntValue = (Integer ) dbMap.get(oneKey); 513 514 String oneValue = (String ) typeToString.get(oneIntValue); 515 516 if (oneValue == null) { 517 log.warn("Unable to map java.sql.Types value " + 518 oneIntValue.toString() + " to a string. The database " + 519 " may have returned an invalid type map. New type being added..."); 520 typeToString.put(oneIntValue, oneKey); 521 oneValue = (String ) typeToString.get(oneIntValue); 522 } else { 523 sqlToDB.put(oneIntValue, 524 StringUtil.notNull(oneKey).toLowerCase()); 525 expressoToJava.put(StringUtil.notNull(oneKey).toLowerCase(), 526 oneIntValue); 527 } 528 } 529 } catch (DBException de) { 530 log.error("Error initializing types", de); 531 throw new DBException(de); 532 } catch (Throwable t) { 533 log.error("Error initializing types", t); 534 throw new DBException(t); 535 } finally { 536 if (myPool != null) { 537 myPool.release(myConnection); 538 } 539 } 540 541 mergeTypeMappings(); 542 } 543 544 private void buildExpressoToSQL() throws DBException { 545 546 expressoToSQL.put(DBField.ARRAY_TYPE, "ARRAY"); 547 expressoToSQL.put(DBField.BIGINT_TYPE, "BIGINT"); 548 549 expressoToSQL.put(DBField.LONG_TYPE, "BIGINT"); 551 expressoToSQL.put(DBField.BINARY_TYPE, "BINARY"); 552 expressoToSQL.put(DBField.BIT_TYPE, "BIT"); 553 554 expressoToSQL.put(DBField.BOOLEAN_TYPE, "BIT"); 556 expressoToSQL.put(DBField.BLOB_TYPE, "BLOB"); 557 expressoToSQL.put(DBField.CHAR_TYPE, "CHAR"); 558 expressoToSQL.put(DBField.CLOB_TYPE, "CLOB"); 559 expressoToSQL.put(DBField.DATE_TYPE, "DATE"); 560 expressoToSQL.put(DBField.DECIMAL_TYPE, "DECIMAL"); 561 expressoToSQL.put("distinct", "DISTINCT"); 562 expressoToSQL.put(DBField.DOUBLE_TYPE, "DOUBLE"); 563 expressoToSQL.put(DBField.FLOAT_TYPE, "FLOAT"); 564 expressoToSQL.put(DBField.INTEGER_TYPE, "INTEGER"); 565 566 expressoToSQL.put(DBField.INT_TYPE, "INTEGER"); 568 expressoToSQL.put(DBField.JAVA_OBJECT, "JAVA_OBJECT"); 569 expressoToSQL.put(DBField.LONGVARBINARY, "LONGVARBINARY"); 570 expressoToSQL.put(DBField.LONGVARCHAR_TYPE, "LONGVARCHAR"); 571 expressoToSQL.put(DBField.NUMERIC_TYPE, "NUMERIC"); 572 expressoToSQL.put(DBField.OTHER_TYPE, "OTHER"); 573 expressoToSQL.put(DBField.REAL_TYPE, "REAL"); 574 expressoToSQL.put(DBField.REF_TYPE, "REF"); 575 expressoToSQL.put(DBField.SMALLINT_TYPE, "SMALLINT"); 576 expressoToSQL.put(DBField.STRUCT_TYPE, "STRUCT"); 577 expressoToSQL.put(DBField.TIME_TYPE, "TIME"); 578 expressoToSQL.put(DBField.TIMESTAMP_TYPE, "TIMESTAMP"); 579 580 expressoToSQL.put(DBField.DATETIME_TYPE, "TIMESTAMP"); 582 expressoToSQL.put(DBField.TINYINT_TYPE, "TINYINT"); 583 expressoToSQL.put(DBField.VARBINARY_TYPE, "VARBINARY"); 584 expressoToSQL.put(DBField.VARCHAR_TYPE, "VARCHAR"); 585 586 expressoToSQL.put(DBField.TEXT_TYPE, "LONGVARCHAR"); 588 589 expressoToSQL.put(DBField.AUTOINC_TYPE, "INTEGER"); 591 592 602 TypeMappingConfig oneMap = null; 603 604 for (Enumeration e = this.getTypeMappings().elements(); 605 e.hasMoreElements();) { 606 oneMap = (TypeMappingConfig) e.nextElement(); 607 608 if ((oneMap.getExpressoType() != null) && 609 (oneMap.getJavaType() != null)) { 610 expressoToSQL.put(oneMap.getExpressoType(), oneMap.getJavaType()); 611 } 612 } 613 } 614 615 619 private void buildSqlToDB() { 620 623 sqlToDB.put(new Integer (java.sql.Types.INTEGER), DBField.INT_TYPE); 624 sqlToDB.put(new Integer (java.sql.Types.VARCHAR), DBField.VARCHAR_TYPE); 625 sqlToDB.put(new Integer (java.sql.Types.CHAR), DBField.CHAR_TYPE); 626 sqlToDB.put(new Integer (java.sql.Types.DATE), DBField.DATE_TYPE); 627 sqlToDB.put(new Integer (java.sql.Types.TIMESTAMP), DBField.DATETIME_TYPE); 628 sqlToDB.put(new Integer (java.sql.Types.TIME), DBField.TIME_TYPE); 629 sqlToDB.put(new Integer (java.sql.Types.FLOAT), DBField.FLOAT_TYPE); 630 sqlToDB.put(new Integer (java.sql.Types.DOUBLE), DBField.DOUBLE_TYPE); 631 sqlToDB.put(new Integer (java.sql.Types.LONGVARCHAR), 632 DBField.LONGVARCHAR_TYPE); 633 sqlToDB.put(new Integer (java.sql.Types.REAL), DBField.REAL_TYPE); 634 sqlToDB.put(new Integer (java.sql.Types.SMALLINT), DBField.SMALLINT_TYPE); 635 sqlToDB.put(new Integer (java.sql.Types.TINYINT), DBField.TINYINT_TYPE); 636 sqlToDB.put(new Integer (java.sql.Types.NUMERIC), DBField.NUMERIC_TYPE); 637 sqlToDB.put(new Integer (java.sql.Types.DECIMAL), DBField.DECIMAL_TYPE); 638 sqlToDB.put(new Integer (java.sql.Types.BIGINT), DBField.LONG_TYPE); 639 sqlToDB.put(new Integer (java.sql.Types.ARRAY), DBField.ARRAY_TYPE); 640 sqlToDB.put(new Integer (java.sql.Types.BINARY), DBField.BINARY_TYPE); 641 sqlToDB.put(new Integer (java.sql.Types.BIT), DBField.BIT_TYPE); 642 sqlToDB.put(new Integer (java.sql.Types.BLOB), DBField.BLOB_TYPE); 643 sqlToDB.put(new Integer (java.sql.Types.CLOB), DBField.CLOB_TYPE); 644 sqlToDB.put(new Integer (java.sql.Types.DISTINCT), "distinct"); 645 sqlToDB.put(new Integer (java.sql.Types.JAVA_OBJECT), DBField.JAVA_OBJECT); 646 sqlToDB.put(new Integer (java.sql.Types.LONGVARBINARY), 647 DBField.LONGVARBINARY); 648 sqlToDB.put(new Integer (java.sql.Types.NULL), DBField.NULL_TYPE); 649 sqlToDB.put(new Integer (java.sql.Types.OTHER), DBField.OTHER_TYPE); 650 sqlToDB.put(new Integer (java.sql.Types.REF), DBField.REF_TYPE); 651 sqlToDB.put(new Integer (java.sql.Types.STRUCT), "struct"); 652 sqlToDB.put(new Integer (java.sql.Types.VARBINARY), 653 DBField.VARBINARY_TYPE); 654 } 655 656 659 private void buildSqlTypeNames() { 660 sqlTypeNames.put(new Integer (java.sql.Types.LONGVARCHAR), 664 "java.sql.Types.LONGVARCHAR"); 665 sqlTypeNames.put(new Integer (java.sql.Types.ARRAY), 666 "java.sql.Types.ARRAY"); 667 sqlTypeNames.put(new Integer (java.sql.Types.BIGINT), 668 "java.sql.Types.BIGINT"); 669 sqlTypeNames.put(new Integer (java.sql.Types.BINARY), 670 "java.sql.Types.BINARY"); 671 sqlTypeNames.put(new Integer (java.sql.Types.BIT), "java.sql.Types.BIT"); 672 sqlTypeNames.put(new Integer (java.sql.Types.BLOB), "java.sql.Types.BLOB"); 673 sqlTypeNames.put(new Integer (java.sql.Types.CHAR), "java.sql.Types.CHAR"); 674 sqlTypeNames.put(new Integer (java.sql.Types.CLOB), "java.sql.Types.CLOB"); 675 sqlTypeNames.put(new Integer (java.sql.Types.DATE), "java.sql.Types.DATE"); 676 sqlTypeNames.put(new Integer (java.sql.Types.DECIMAL), 677 "java.sql.Types.DECIMAL"); 678 sqlTypeNames.put(new Integer (java.sql.Types.DISTINCT), 679 "java.sql.Types.DISTINCT"); 680 sqlTypeNames.put(new Integer (java.sql.Types.DOUBLE), 681 "java.sql.Types.DOUBLE"); 682 sqlTypeNames.put(new Integer (java.sql.Types.FLOAT), 683 "java.sql.Types.FLOAT"); 684 sqlTypeNames.put(new Integer (java.sql.Types.INTEGER), 685 "java.sql.Types.INTEGER"); 686 sqlTypeNames.put(new Integer (java.sql.Types.JAVA_OBJECT), 687 "java.sql.Types.JAVA_OBJECT"); 688 sqlTypeNames.put(new Integer (java.sql.Types.LONGVARBINARY), 689 "java.sql.Types.LONGVARBINARY"); 690 sqlTypeNames.put(new Integer (java.sql.Types.LONGVARCHAR), 691 "java.sql.Types.LONGVARCHAR"); 692 sqlTypeNames.put(new Integer (java.sql.Types.NUMERIC), 693 "java.sql.Types.NUMERIC"); 694 sqlTypeNames.put(new Integer (java.sql.Types.OTHER), 695 "java.sql.Types.OTHER"); 696 sqlTypeNames.put(new Integer (java.sql.Types.REAL), "java.sql.Types.REAL"); 697 sqlTypeNames.put(new Integer (java.sql.Types.REF), "java.sql.Types.REF"); 698 sqlTypeNames.put(new Integer (java.sql.Types.SMALLINT), 699 "java.sql.Types.SMALLINT"); 700 sqlTypeNames.put(new Integer (java.sql.Types.STRUCT), 701 "java.sql.Types.STRUCT"); 702 sqlTypeNames.put(new Integer (java.sql.Types.TIME), "java.sql.Types.TIME"); 703 sqlTypeNames.put(new Integer (java.sql.Types.TIMESTAMP), 704 "java.sql.Types.TIMESTAMP"); 705 sqlTypeNames.put(new Integer (java.sql.Types.TINYINT), 706 "java.sql.Types.TINYINT"); 707 sqlTypeNames.put(new Integer (java.sql.Types.VARBINARY), 708 "java.sql.Types.VARBINARY"); 709 sqlTypeNames.put(new Integer (java.sql.Types.VARCHAR), 710 "java.sql.Types.VARCHAR"); 711 } 712 713 716 private void buildTypeToString() { 717 typeToString.put(new Integer (java.sql.Types.LONGVARCHAR), "LONGVARCHAR"); 718 typeToString.put(new Integer (java.sql.Types.ARRAY), "ARRAY"); 719 typeToString.put(new Integer (java.sql.Types.BIGINT), "BIGINT"); 720 typeToString.put(new Integer (java.sql.Types.BINARY), "BINARY"); 721 typeToString.put(new Integer (java.sql.Types.BIT), "BIT"); 722 typeToString.put(new Integer (java.sql.Types.BLOB), "BLOB"); 723 typeToString.put(new Integer ![]() |