/* * * SchemaCrawler * http://sourceforge.net/projects/schemacrawler * Copyright (c) 2000-2009, Sualeh Fatehi. * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * */ package schemacrawler.crawl; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.Field; import java.sql.Types; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; /** * Utility to work with java.sql.Types, and Java class name mappings. * * @author Sualeh Fatehi */ public final class JavaSqlTypesUtility { public static enum JavaSqlTypeGroup { unknown, binary, bit, character, temporal, id, integer, real, reference, url, xml; } private static final Logger LOGGER = Logger .getLogger(JavaSqlTypesUtility.class.getName()); private static final Map<Integer, JavaSqlType> JAVA_SQL_TYPES = readJavaSqlTypes(); private static final Map<String, JavaSqlTypeGroup> JAVA_SQL_TYPES_GROUPS = readJavaSqlTypesGroupsMap(); /** * Lookup java.sql.Types type, and return more detailed information, * including the mapped Java class. * * @param type * java.sql.Types type * @return JavaSqlType type */ public static JavaSqlType lookupSqlDataType(final int type) { JavaSqlType sqlDataType = JAVA_SQL_TYPES.get(type); if (sqlDataType == null) { sqlDataType = JavaSqlType.UNKNOWN; } return sqlDataType; } /** * Lookup java.sql.Types type, and return the type group. * * @param type * java.sql.Types type * @return JavaSqlTypeGroup group */ public static JavaSqlTypeGroup lookupSqlDataTypeGroup(final int type) { final JavaSqlType sqlDataType = lookupSqlDataType(type); JavaSqlTypeGroup javaSqlTypeGroup = JAVA_SQL_TYPES_GROUPS.get(sqlDataType .getJavaSqlTypeName()); if (javaSqlTypeGroup == null) { javaSqlTypeGroup = JavaSqlTypeGroup.unknown; } return javaSqlTypeGroup; } public static void main(final String[] args) throws IOException { for (final JavaSqlType javaSqlType: JAVA_SQL_TYPES.values()) { System.out.println(javaSqlType); } final Writer writer; if (args.length > 0) { writer = new FileWriter(new File(args[0])); } else { writer = new OutputStreamWriter(System.out); } writer.write(String.format("# java.sql.Types from Java %s %s\n", System .getProperty("java.version"), System.getProperty("java.vendor"))); final List<JavaSqlType> javaSqlTypes = new ArrayList<JavaSqlType>(getJavaSqlTypes() .values()); Collections.sort(javaSqlTypes); for (final JavaSqlType sqlDataType: javaSqlTypes) { writer.write(String.format("%s=%d\n", sqlDataType.getJavaSqlTypeName(), sqlDataType.getJavaSqlType())); } writer.flush(); writer.close(); } private static Map<Integer, JavaSqlType> getJavaSqlTypes() { final Map<String, Class<?>> javaSqlTypesClassMap = getJavaSqlTypesPrimitivesClassMap(); final Map<Integer, JavaSqlType> javaSqlTypes = new HashMap<Integer, JavaSqlType>(); final Field[] javaSqlTypesFields = Types.class.getFields(); for (final Field field: javaSqlTypesFields) { try { final String javaSqlTypeName = field.getName(); final Integer javaSqlType = (Integer) field.get(null); final Class<?> javaSqlTypeClass = javaSqlTypesClassMap .get(javaSqlTypeName); javaSqlTypes.put(javaSqlType, new JavaSqlType(javaSqlType, javaSqlTypeName, javaSqlTypeClass)); } catch (final SecurityException e) { LOGGER.log(Level.WARNING, "Could not access java.sql.Types", e); continue; } catch (final IllegalAccessException e) { LOGGER.log(Level.WARNING, "Could not access java.sql.Types", e); continue; } } return javaSqlTypes; } /** * Map java.sql.Types to Java classes. Since this information is not * available in the JDK, we need to hard-code it. * * @see <a * href="http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/mapping.html#1004791">Mapping * SQL and Java Types</a> */ private static Map<String, Class<?>> getJavaSqlTypesPrimitivesClassMap() { final Map<String, Class<?>> javaSqlTypesClassMap = new TreeMap<String, Class<?>>(); javaSqlTypesClassMap.put("BIGINT", long.class); javaSqlTypesClassMap.put("BINARY", byte[].class); javaSqlTypesClassMap.put("BIT", boolean.class); javaSqlTypesClassMap.put("BOOLEAN", boolean.class); javaSqlTypesClassMap.put("CHAR", String.class); javaSqlTypesClassMap.put("DATALINK", java.net.URL.class); javaSqlTypesClassMap.put("DECIMAL", java.math.BigDecimal.class); javaSqlTypesClassMap.put("DOUBLE", double.class); javaSqlTypesClassMap.put("FLOAT", double.class); javaSqlTypesClassMap.put("INTEGER", int.class); javaSqlTypesClassMap.put("JAVA_OBJECT", Object.class); javaSqlTypesClassMap.put("LONGNVARCHAR", String.class); javaSqlTypesClassMap.put("LONGVARBINARY", byte[].class); javaSqlTypesClassMap.put("LONGVARCHAR", String.class); javaSqlTypesClassMap.put("NCHAR", String.class); javaSqlTypesClassMap.put("NULL", void.class); javaSqlTypesClassMap.put("NUMERIC", java.math.BigDecimal.class); javaSqlTypesClassMap.put("NVARCHAR", String.class); javaSqlTypesClassMap.put("OTHER", Object.class); javaSqlTypesClassMap.put("REAL", float.class); javaSqlTypesClassMap.put("SMALLINT", short.class); javaSqlTypesClassMap.put("TINYINT", byte.class); javaSqlTypesClassMap.put("VARBINARY", byte[].class); javaSqlTypesClassMap.put("VARCHAR", String.class); return Collections.unmodifiableMap(javaSqlTypesClassMap); } private static Map<Integer, JavaSqlType> readJavaSqlTypes() { final Map<String, Class<?>> javaSqlTypesClassMap = getJavaSqlTypesPrimitivesClassMap(); final Properties javaSqlTypesClassNames = readJavaSqlTypesClassNameMap(); final Map<Integer, JavaSqlType> javaSqlTypes = new HashMap<Integer, JavaSqlType>(); final Properties javaSqlTypesProperties = readPropertiesResource("/java.sql.Types.properties"); for (final Entry<Object, Object> javaSqlTypesEntry: javaSqlTypesProperties .entrySet()) { if (javaSqlTypesEntry.getKey() != null && javaSqlTypesEntry.getValue() != null) { final Integer javaSqlType = Integer.parseInt(javaSqlTypesEntry .getValue().toString()); final String javaSqlTypeName = javaSqlTypesEntry.getKey().toString(); Class<?> javaSqlTypeClass; final String javaSqlTypesClassName = javaSqlTypesClassNames .getProperty(javaSqlTypeName); try { if (javaSqlTypesClassName != null) { javaSqlTypeClass = Class.forName(javaSqlTypesClassName); } else { javaSqlTypeClass = null; } } catch (final Throwable e) // A number of exceptions or errors // could occur { LOGGER.log(Level.WARNING, "Cannot load class, " + javaSqlTypesClassName, e); javaSqlTypeClass = null; } if (javaSqlTypeClass == null) { javaSqlTypeClass = javaSqlTypesClassMap.get(javaSqlTypeName); } if (javaSqlTypeClass != null) { javaSqlTypes.put(javaSqlType, new JavaSqlType(javaSqlType, javaSqlTypeName, javaSqlTypeClass)); } else { javaSqlTypes.put(javaSqlType, new JavaSqlType(javaSqlType, javaSqlTypeName, javaSqlTypesClassName)); } } } return Collections.unmodifiableMap(javaSqlTypes); } private static Properties readJavaSqlTypesClassNameMap() { return readPropertiesResource("/java.sql.Types.mappings.properties"); } private static Map<String, JavaSqlTypeGroup> readJavaSqlTypesGroupsMap() { final Map<String, JavaSqlTypeGroup> javaSqlTypesGroupsMap = new HashMap<String, JavaSqlTypeGroup>(); final Properties javaSqlTypesGroups = readPropertiesResource("/java.sql.Types.groups.properties"); for (final Entry<Object, Object> javaSqlTypesGroupsEntry: javaSqlTypesGroups .entrySet()) { try { final String javaSqlTypeName = javaSqlTypesGroupsEntry.getKey() .toString(); final JavaSqlTypeGroup group = JavaSqlTypeGroup .valueOf(javaSqlTypesGroupsEntry.getValue().toString()); javaSqlTypesGroupsMap.put(javaSqlTypeName, group); } catch (final Exception e) { continue; } } return Collections.unmodifiableMap(javaSqlTypesGroupsMap); } private static Properties readPropertiesResource(final String resource) { final Properties properties = new Properties(); final InputStream inputStream = JavaSqlTypesUtility.class .getResourceAsStream(resource); if (inputStream != null) { try { properties.load(inputStream); } catch (final IOException e) { LOGGER.log(Level.WARNING, "Could not read internal resource, " + resource, e); } finally { try { inputStream.close(); } catch (final IOException e) { // Ignore } } } return properties; } private JavaSqlTypesUtility() { } }