001: //$Id: Environment.java 11535 2007-05-18 12:34:04Z steve.ebersole@jboss.com $
002: package org.hibernate.cfg;
003:
004: import java.io.IOException;
005: import java.io.InputStream;
006: import java.sql.Connection;
007: import java.sql.Statement;
008: import java.sql.Timestamp;
009: import java.util.HashMap;
010: import java.util.Iterator;
011: import java.util.Map;
012: import java.util.Properties;
013:
014: import org.apache.commons.logging.Log;
015: import org.apache.commons.logging.LogFactory;
016:
017: import org.hibernate.HibernateException;
018: import org.hibernate.bytecode.BytecodeProvider;
019: import org.hibernate.util.ConfigHelper;
020: import org.hibernate.util.PropertiesHelper;
021:
022: /**
023: * Provides access to configuration info passed in <tt>Properties</tt> objects.
024: * <br><br>
025: * Hibernate has two property scopes:
026: * <ul>
027: * <li><b>Factory-level</b> properties may be passed to the <tt>SessionFactory</tt> when it
028: * instantiated. Each instance might have different property values. If no
029: * properties are specified, the factory calls <tt>Environment.getProperties()</tt>.
030: * <li><b>System-level</b> properties are shared by all factory instances and are always
031: * determined by the <tt>Environment</tt> properties.
032: * </ul>
033: * The only system-level properties are
034: * <ul>
035: * <li><tt>hibernate.jdbc.use_streams_for_binary</tt>
036: * <li><tt>hibernate.cglib.use_reflection_optimizer</tt>
037: * </ul>
038: * <tt>Environment</tt> properties are populated by calling <tt>System.getProperties()</tt>
039: * and then from a resource named <tt>/hibernate.properties</tt> if it exists. System
040: * properties override properties specified in <tt>hibernate.properties</tt>.<br>
041: * <br>
042: * The <tt>SessionFactory</tt> is controlled by the following properties.
043: * Properties may be either be <tt>System</tt> properties, properties
044: * defined in a resource named <tt>/hibernate.properties</tt> or an instance of
045: * <tt>java.util.Properties</tt> passed to
046: * <tt>Configuration.buildSessionFactory()</tt><br>
047: * <br>
048: * <table>
049: * <tr><td><b>property</b></td><td><b>meaning</b></td></tr>
050: * <tr>
051: * <td><tt>hibernate.dialect</tt></td>
052: * <td>classname of <tt>org.hibernate.dialect.Dialect</tt> subclass</td>
053: * </tr>
054: * <tr>
055: * <td><tt>hibernate.cache.provider_class</tt></td>
056: * <td>classname of <tt>org.hibernate.cache.CacheProvider</tt>
057: * subclass (if not specified EHCache is used)</td>
058: * </tr>
059: * <tr>
060: * <td><tt>hibernate.connection.provider_class</tt></td>
061: * <td>classname of <tt>org.hibernate.connection.ConnectionProvider</tt>
062: * subclass (if not specified hueristics are used)</td>
063: * </tr>
064: * <tr><td><tt>hibernate.connection.username</tt></td><td>database username</td></tr>
065: * <tr><td><tt>hibernate.connection.password</tt></td><td>database password</td></tr>
066: * <tr>
067: * <td><tt>hibernate.connection.url</tt></td>
068: * <td>JDBC URL (when using <tt>java.sql.DriverManager</tt>)</td>
069: * </tr>
070: * <tr>
071: * <td><tt>hibernate.connection.driver_class</tt></td>
072: * <td>classname of JDBC driver</td>
073: * </tr>
074: * <tr>
075: * <td><tt>hibernate.connection.isolation</tt></td>
076: * <td>JDBC transaction isolation level (only when using
077: * <tt>java.sql.DriverManager</tt>)
078: * </td>
079: * </tr>
080: * <td><tt>hibernate.connection.pool_size</tt></td>
081: * <td>the maximum size of the connection pool (only when using
082: * <tt>java.sql.DriverManager</tt>)
083: * </td>
084: * </tr>
085: * <tr>
086: * <td><tt>hibernate.connection.datasource</tt></td>
087: * <td>databasource JNDI name (when using <tt>javax.sql.Datasource</tt>)</td>
088: * </tr>
089: * <tr>
090: * <td><tt>hibernate.jndi.url</tt></td><td>JNDI <tt>InitialContext</tt> URL</td>
091: * </tr>
092: * <tr>
093: * <td><tt>hibernate.jndi.class</tt></td><td>JNDI <tt>InitialContext</tt> classname</td>
094: * </tr>
095: * <tr>
096: * <td><tt>hibernate.max_fetch_depth</tt></td>
097: * <td>maximum depth of outer join fetching</td>
098: * </tr>
099: * <tr>
100: * <td><tt>hibernate.jdbc.batch_size</tt></td>
101: * <td>enable use of JDBC2 batch API for drivers which support it</td>
102: * </tr>
103: * <tr>
104: * <td><tt>hibernate.jdbc.fetch_size</tt></td>
105: * <td>set the JDBC fetch size</td>
106: * </tr>
107: * <tr>
108: * <td><tt>hibernate.jdbc.use_scrollable_resultset</tt></td>
109: * <td>enable use of JDBC2 scrollable resultsets (you only need this specify
110: * this property when using user supplied connections)</td>
111: * </tr>
112: * <tr>
113: * <td><tt>hibernate.jdbc.use_getGeneratedKeys</tt></td>
114: * <td>enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve
115: * natively generated keys after insert. Requires JDBC3+ driver and JRE1.4+</td>
116: * </tr>
117: * <tr>
118: * <td><tt>hibernate.hbm2ddl.auto</tt></td>
119: * <td>enable auto DDL export</td>
120: * </tr>
121: * <tr>
122: * <td><tt>hibernate.default_schema</tt></td>
123: * <td>use given schema name for unqualified tables (always optional)</td>
124: * </tr>
125: * <tr>
126: * <td><tt>hibernate.default_catalog</tt></td>
127: * <td>use given catalog name for unqualified tables (always optional)</td>
128: * </tr>
129: * <tr>
130: * <td><tt>hibernate.session_factory_name</tt></td>
131: * <td>If set, the factory attempts to bind this name to itself in the
132: * JNDI context. This name is also used to support cross JVM <tt>
133: * Session</tt> (de)serialization.</td>
134: * </tr>
135: * <tr>
136: * <td><tt>hibernate.transaction.manager_lookup_class</tt></td>
137: * <td>classname of <tt>org.hibernate.transaction.TransactionManagerLookup</tt>
138: * implementor</td>
139: * </tr>
140: * <tr>
141: * <td><tt>hibernate.transaction.factory_class</tt></td>
142: * <td>the factory to use for instantiating <tt>Transaction</tt>s.
143: * (Defaults to <tt>JDBCTransactionFactory</tt>.)</td>
144: * </tr>
145: * <tr>
146: * <td><tt>hibernate.query.substitutions</tt></td><td>query language token substitutions</td>
147: * </tr>
148: * </table>
149: *
150: * @see org.hibernate.SessionFactory
151: * @author Gavin King
152: */
153: public final class Environment {
154:
155: public static final String VERSION = "3.2.4.sp1";
156:
157: /**
158: * <tt>ConnectionProvider</tt> implementor to use when obtaining connections
159: */
160: public static final String CONNECTION_PROVIDER = "hibernate.connection.provider_class";
161: /**
162: * JDBC driver class
163: */
164: public static final String DRIVER = "hibernate.connection.driver_class";
165: /**
166: * JDBC transaction isolation level
167: */
168: public static final String ISOLATION = "hibernate.connection.isolation";
169: /**
170: * JDBC URL
171: */
172: public static final String URL = "hibernate.connection.url";
173: /**
174: * JDBC user
175: */
176: public static final String USER = "hibernate.connection.username";
177: /**
178: * JDBC password
179: */
180: public static final String PASS = "hibernate.connection.password";
181: /**
182: * JDBC autocommit mode
183: */
184: public static final String AUTOCOMMIT = "hibernate.connection.autocommit";
185: /**
186: * Maximum number of inactive connections for Hibernate's connection pool
187: */
188: public static final String POOL_SIZE = "hibernate.connection.pool_size";
189: /**
190: * <tt>java.sql.Datasource</tt> JNDI name
191: */
192: public static final String DATASOURCE = "hibernate.connection.datasource";
193: /**
194: * prefix for arbitrary JDBC connection properties
195: */
196: public static final String CONNECTION_PREFIX = "hibernate.connection";
197:
198: /**
199: * JNDI initial context class, <tt>Context.INITIAL_CONTEXT_FACTORY</tt>
200: */
201: public static final String JNDI_CLASS = "hibernate.jndi.class";
202: /**
203: * JNDI provider URL, <tt>Context.PROVIDER_URL</tt>
204: */
205: public static final String JNDI_URL = "hibernate.jndi.url";
206: /**
207: * prefix for arbitrary JNDI <tt>InitialContext</tt> properties
208: */
209: public static final String JNDI_PREFIX = "hibernate.jndi";
210: /**
211: * JNDI name to bind to <tt>SessionFactory</tt>
212: */
213: public static final String SESSION_FACTORY_NAME = "hibernate.session_factory_name";
214:
215: /**
216: * Hibernate SQL <tt>Dialect</tt> class
217: */
218: public static final String DIALECT = "hibernate.dialect";
219: /**
220: * A default database schema (owner) name to use for unqualified tablenames
221: */
222: public static final String DEFAULT_SCHEMA = "hibernate.default_schema";
223: /**
224: * A default database catalog name to use for unqualified tablenames
225: */
226: public static final String DEFAULT_CATALOG = "hibernate.default_catalog";
227:
228: /**
229: * Enable logging of generated SQL to the console
230: */
231: public static final String SHOW_SQL = "hibernate.show_sql";
232: /**
233: * Enable formatting of SQL logged to the console
234: */
235: public static final String FORMAT_SQL = "hibernate.format_sql";
236: /**
237: * Add comments to the generated SQL
238: */
239: public static final String USE_SQL_COMMENTS = "hibernate.use_sql_comments";
240: /**
241: * Maximum depth of outer join fetching
242: */
243: public static final String MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
244: /**
245: * The default batch size for batch fetching
246: */
247: public static final String DEFAULT_BATCH_FETCH_SIZE = "hibernate.default_batch_fetch_size";
248: /**
249: * Use <tt>java.io</tt> streams to read / write binary data from / to JDBC
250: */
251: public static final String USE_STREAMS_FOR_BINARY = "hibernate.jdbc.use_streams_for_binary";
252: /**
253: * Use JDBC scrollable <tt>ResultSet</tt>s. This property is only necessary when there is
254: * no <tt>ConnectionProvider</tt>, ie. the user is supplying JDBC connections.
255: */
256: public static final String USE_SCROLLABLE_RESULTSET = "hibernate.jdbc.use_scrollable_resultset";
257: /**
258: * Tells the JDBC driver to attempt to retrieve row Id with the JDBC 3.0 PreparedStatement.getGeneratedKeys()
259: * method. In general, performance will be better if this property is set to true and the underlying
260: * JDBC driver supports getGeneratedKeys().
261: */
262: public static final String USE_GET_GENERATED_KEYS = "hibernate.jdbc.use_get_generated_keys";
263: /**
264: * Gives the JDBC driver a hint as to the number of rows that should be fetched from the database
265: * when more rows are needed. If <tt>0</tt>, JDBC driver default settings will be used.
266: */
267: public static final String STATEMENT_FETCH_SIZE = "hibernate.jdbc.fetch_size";
268: /**
269: * Maximum JDBC batch size. A nonzero value enables batch updates.
270: */
271: public static final String STATEMENT_BATCH_SIZE = "hibernate.jdbc.batch_size";
272: /**
273: * Select a custom batcher.
274: */
275: public static final String BATCH_STRATEGY = "hibernate.jdbc.factory_class";
276: /**
277: * Should versioned data be included in batching?
278: */
279: public static final String BATCH_VERSIONED_DATA = "hibernate.jdbc.batch_versioned_data";
280: /**
281: * An XSLT resource used to generate "custom" XML
282: */
283: public static final String OUTPUT_STYLESHEET = "hibernate.xml.output_stylesheet";
284:
285: /**
286: * Maximum size of C3P0 connection pool
287: */
288: public static final String C3P0_MAX_SIZE = "hibernate.c3p0.max_size";
289: /**
290: * Minimum size of C3P0 connection pool
291: */
292: public static final String C3P0_MIN_SIZE = "hibernate.c3p0.min_size";
293:
294: /**
295: * Maximum idle time for C3P0 connection pool
296: */
297: public static final String C3P0_TIMEOUT = "hibernate.c3p0.timeout";
298: /**
299: * Maximum size of C3P0 statement cache
300: */
301: public static final String C3P0_MAX_STATEMENTS = "hibernate.c3p0.max_statements";
302: /**
303: * Number of connections acquired when pool is exhausted
304: */
305: public static final String C3P0_ACQUIRE_INCREMENT = "hibernate.c3p0.acquire_increment";
306: /**
307: * Idle time before a C3P0 pooled connection is validated
308: */
309: public static final String C3P0_IDLE_TEST_PERIOD = "hibernate.c3p0.idle_test_period";
310:
311: /**
312: * Proxool/Hibernate property prefix
313: */
314: public static final String PROXOOL_PREFIX = "hibernate.proxool";
315: /**
316: * Proxool property to configure the Proxool Provider using an XML (<tt>/path/to/file.xml</tt>)
317: */
318: public static final String PROXOOL_XML = "hibernate.proxool.xml";
319: /**
320: * Proxool property to configure the Proxool Provider using a properties file (<tt>/path/to/proxool.properties</tt>)
321: */
322: public static final String PROXOOL_PROPERTIES = "hibernate.proxool.properties";
323: /**
324: * Proxool property to configure the Proxool Provider from an already existing pool (<tt>true</tt> / <tt>false</tt>)
325: */
326: public static final String PROXOOL_EXISTING_POOL = "hibernate.proxool.existing_pool";
327: /**
328: * Proxool property with the Proxool pool alias to use
329: * (Required for <tt>PROXOOL_EXISTING_POOL</tt>, <tt>PROXOOL_PROPERTIES</tt>, or
330: * <tt>PROXOOL_XML</tt>)
331: */
332: public static final String PROXOOL_POOL_ALIAS = "hibernate.proxool.pool_alias";
333:
334: /**
335: * Enable automatic session close at end of transaction
336: */
337: public static final String AUTO_CLOSE_SESSION = "hibernate.transaction.auto_close_session";
338: /**
339: * Enable automatic flush during the JTA <tt>beforeCompletion()</tt> callback
340: */
341: public static final String FLUSH_BEFORE_COMPLETION = "hibernate.transaction.flush_before_completion";
342: /**
343: * Specifies how Hibernate should release JDBC connections.
344: */
345: public static final String RELEASE_CONNECTIONS = "hibernate.connection.release_mode";
346: /**
347: * Context scoping impl for {@link org.hibernate.SessionFactory#getCurrentSession()} processing.
348: */
349: public static final String CURRENT_SESSION_CONTEXT_CLASS = "hibernate.current_session_context_class";
350: /**
351: * <tt>TransactionFactory</tt> implementor to use for creating <tt>Transaction</tt>s
352: */
353: public static final String TRANSACTION_STRATEGY = "hibernate.transaction.factory_class";
354: /**
355: * <tt>TransactionManagerLookup</tt> implementor to use for obtaining the <tt>TransactionManager</tt>
356: */
357: public static final String TRANSACTION_MANAGER_STRATEGY = "hibernate.transaction.manager_lookup_class";
358: /**
359: * JNDI name of JTA <tt>UserTransaction</tt> object
360: */
361: public static final String USER_TRANSACTION = "jta.UserTransaction";
362:
363: /**
364: * The <tt>CacheProvider</tt> implementation class
365: */
366: public static final String CACHE_PROVIDER = "hibernate.cache.provider_class";
367: /**
368: * The <tt>CacheProvider</tt> implementation class
369: */
370: public static final String CACHE_PROVIDER_CONFIG = "hibernate.cache.provider_configuration_file_resource_path";
371: /**
372: * The <tt>CacheProvider</tt> JNDI namespace, if pre-bound to JNDI.
373: */
374: public static final String CACHE_NAMESPACE = "hibernate.cache.jndi";
375: /**
376: * Enable the query cache (disabled by default)
377: */
378: public static final String USE_QUERY_CACHE = "hibernate.cache.use_query_cache";
379: /**
380: * The <tt>QueryCacheFactory</tt> implementation class.
381: */
382: public static final String QUERY_CACHE_FACTORY = "hibernate.cache.query_cache_factory";
383: /**
384: * Enable the second-level cache (enabled by default)
385: */
386: public static final String USE_SECOND_LEVEL_CACHE = "hibernate.cache.use_second_level_cache";
387: /**
388: * Optimize the cache for mimimal puts instead of minimal gets
389: */
390: public static final String USE_MINIMAL_PUTS = "hibernate.cache.use_minimal_puts";
391: /**
392: * The <tt>CacheProvider</tt> region name prefix
393: */
394: public static final String CACHE_REGION_PREFIX = "hibernate.cache.region_prefix";
395: /**
396: * Enable use of structured second-level cache entries
397: */
398: public static final String USE_STRUCTURED_CACHE = "hibernate.cache.use_structured_entries";
399:
400: /**
401: * Enable statistics collection
402: */
403: public static final String GENERATE_STATISTICS = "hibernate.generate_statistics";
404:
405: public static final String USE_IDENTIFIER_ROLLBACK = "hibernate.use_identifier_rollback";
406:
407: /**
408: * Use bytecode libraries optimized property access
409: */
410: public static final String USE_REFLECTION_OPTIMIZER = "hibernate.bytecode.use_reflection_optimizer";
411:
412: /**
413: * The classname of the HQL query parser factory
414: */
415: public static final String QUERY_TRANSLATOR = "hibernate.query.factory_class";
416:
417: /**
418: * A comma-seperated list of token substitutions to use when translating a Hibernate
419: * query to SQL
420: */
421: public static final String QUERY_SUBSTITUTIONS = "hibernate.query.substitutions";
422:
423: /**
424: * Should named queries be checked during startup (the default is enabled).
425: * <p/>
426: * Mainly intended for test environments.
427: */
428: public static final String QUERY_STARTUP_CHECKING = "hibernate.query.startup_check";
429:
430: /**
431: * Auto export/update schema using hbm2ddl tool. Valid values are <tt>update</tt>,
432: * <tt>create</tt>, <tt>create-drop</tt> and <tt>validate</tt>.
433: */
434: public static final String HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
435:
436: /**
437: * The {@link org.hibernate.exception.SQLExceptionConverter} to use for converting SQLExceptions
438: * to Hibernate's JDBCException hierarchy. The default is to use the configured
439: * {@link org.hibernate.dialect.Dialect}'s preferred SQLExceptionConverter.
440: */
441: public static final String SQL_EXCEPTION_CONVERTER = "hibernate.jdbc.sql_exception_converter";
442:
443: /**
444: * Enable wrapping of JDBC result sets in order to speed up column name lookups for
445: * broken JDBC drivers
446: */
447: public static final String WRAP_RESULT_SETS = "hibernate.jdbc.wrap_result_sets";
448:
449: /**
450: * Enable ordering of update statements by primary key value
451: */
452: public static final String ORDER_UPDATES = "hibernate.order_updates";
453:
454: /**
455: * Enable ordering of insert statements for the purpose of more effecient JDBC batching.
456: */
457: public static final String ORDER_INSERTS = "hibernate.order_inserts";
458:
459: /**
460: * The EntityMode in which set the Session opened from the SessionFactory.
461: */
462: public static final String DEFAULT_ENTITY_MODE = "hibernate.default_entity_mode";
463:
464: /**
465: * The jacc context id of the deployment
466: */
467: public static final String JACC_CONTEXTID = "hibernate.jacc_context_id";
468:
469: public static final String BYTECODE_PROVIDER = "hibernate.bytecode.provider";
470:
471: public static final String JPAQL_STRICT_COMPLIANCE = "hibernate.query.jpaql_strict_compliance";
472:
473: private static final BytecodeProvider BYTECODE_PROVIDER_INSTANCE;
474: private static final boolean ENABLE_BINARY_STREAMS;
475: private static final boolean ENABLE_REFLECTION_OPTIMIZER;
476: private static final boolean JVM_SUPPORTS_LINKED_HASH_COLLECTIONS;
477: private static final boolean JVM_HAS_TIMESTAMP_BUG;
478: private static final boolean JVM_HAS_JDK14_TIMESTAMP;
479: private static final boolean JVM_SUPPORTS_GET_GENERATED_KEYS;
480:
481: private static final Properties GLOBAL_PROPERTIES;
482: private static final HashMap ISOLATION_LEVELS = new HashMap();
483: private static final Map OBSOLETE_PROPERTIES = new HashMap();
484: private static final Map RENAMED_PROPERTIES = new HashMap();
485:
486: private static final Log log = LogFactory.getLog(Environment.class);
487:
488: /**
489: * Issues warnings to the user when any obsolete property names are used.
490: */
491: public static void verifyProperties(Properties props) {
492: Iterator iter = props.keySet().iterator();
493: Map propertiesToAdd = new HashMap();
494: while (iter.hasNext()) {
495: final Object propertyName = iter.next();
496: Object newPropertyName = OBSOLETE_PROPERTIES
497: .get(propertyName);
498: if (newPropertyName != null) {
499: log.warn("Usage of obsolete property: " + propertyName
500: + " no longer supported, use: "
501: + newPropertyName);
502: }
503: newPropertyName = RENAMED_PROPERTIES.get(propertyName);
504: if (newPropertyName != null) {
505: log.warn("Property [" + propertyName
506: + "] has been renamed to [" + newPropertyName
507: + "]; update your properties appropriately");
508: if (!props.containsKey(newPropertyName)) {
509: propertiesToAdd.put(newPropertyName, props
510: .get(propertyName));
511: }
512: }
513: }
514: props.putAll(propertiesToAdd);
515: }
516:
517: static {
518:
519: log.info("Hibernate " + VERSION);
520:
521: RENAMED_PROPERTIES.put(
522: "hibernate.cglib.use_reflection_optimizer",
523: USE_REFLECTION_OPTIMIZER);
524:
525: ISOLATION_LEVELS.put(new Integer(Connection.TRANSACTION_NONE),
526: "NONE");
527: ISOLATION_LEVELS.put(new Integer(
528: Connection.TRANSACTION_READ_UNCOMMITTED),
529: "READ_UNCOMMITTED");
530: ISOLATION_LEVELS.put(new Integer(
531: Connection.TRANSACTION_READ_COMMITTED),
532: "READ_COMMITTED");
533: ISOLATION_LEVELS.put(new Integer(
534: Connection.TRANSACTION_REPEATABLE_READ),
535: "REPEATABLE_READ");
536: ISOLATION_LEVELS.put(new Integer(
537: Connection.TRANSACTION_SERIALIZABLE), "SERIALIZABLE");
538:
539: GLOBAL_PROPERTIES = new Properties();
540: //Set USE_REFLECTION_OPTIMIZER to false to fix HHH-227
541: GLOBAL_PROPERTIES.setProperty(USE_REFLECTION_OPTIMIZER,
542: Boolean.FALSE.toString());
543:
544: try {
545: InputStream stream = ConfigHelper
546: .getResourceAsStream("/hibernate.properties");
547: try {
548: GLOBAL_PROPERTIES.load(stream);
549: log
550: .info("loaded properties from resource hibernate.properties: "
551: + PropertiesHelper.maskOut(
552: GLOBAL_PROPERTIES, PASS));
553: } catch (Exception e) {
554: log
555: .error("problem loading properties from hibernate.properties");
556: } finally {
557: try {
558: stream.close();
559: } catch (IOException ioe) {
560: log
561: .error(
562: "could not close stream on hibernate.properties",
563: ioe);
564: }
565: }
566: } catch (HibernateException he) {
567: log.info("hibernate.properties not found");
568: }
569:
570: try {
571: GLOBAL_PROPERTIES.putAll(System.getProperties());
572: } catch (SecurityException se) {
573: log
574: .warn("could not copy system properties, system properties will be ignored");
575: }
576:
577: verifyProperties(GLOBAL_PROPERTIES);
578:
579: ENABLE_BINARY_STREAMS = PropertiesHelper.getBoolean(
580: USE_STREAMS_FOR_BINARY, GLOBAL_PROPERTIES);
581: ENABLE_REFLECTION_OPTIMIZER = PropertiesHelper.getBoolean(
582: USE_REFLECTION_OPTIMIZER, GLOBAL_PROPERTIES);
583:
584: if (ENABLE_BINARY_STREAMS) {
585: log.info("using java.io streams to persist binary types");
586: }
587: if (ENABLE_REFLECTION_OPTIMIZER) {
588: log.info("using bytecode reflection optimizer");
589: }
590: BYTECODE_PROVIDER_INSTANCE = buildBytecodeProvider(GLOBAL_PROPERTIES);
591:
592: boolean getGeneratedKeysSupport;
593: try {
594: Statement.class.getMethod("getGeneratedKeys", null);
595: getGeneratedKeysSupport = true;
596: } catch (NoSuchMethodException nsme) {
597: getGeneratedKeysSupport = false;
598: }
599: JVM_SUPPORTS_GET_GENERATED_KEYS = getGeneratedKeysSupport;
600: if (!JVM_SUPPORTS_GET_GENERATED_KEYS)
601: log
602: .info("JVM does not support Statement.getGeneratedKeys()");
603:
604: boolean linkedHashSupport;
605: try {
606: Class.forName("java.util.LinkedHashSet");
607: linkedHashSupport = true;
608: } catch (ClassNotFoundException cnfe) {
609: linkedHashSupport = false;
610: }
611: JVM_SUPPORTS_LINKED_HASH_COLLECTIONS = linkedHashSupport;
612: if (!JVM_SUPPORTS_LINKED_HASH_COLLECTIONS)
613: log
614: .info("JVM does not support LinkedHasMap, LinkedHashSet - ordered maps and sets disabled");
615:
616: JVM_HAS_TIMESTAMP_BUG = new Timestamp(123456789).getTime() != 123456789;
617: if (JVM_HAS_TIMESTAMP_BUG)
618: log
619: .info("using workaround for JVM bug in java.sql.Timestamp");
620: Timestamp t = new Timestamp(0);
621: t.setNanos(5 * 1000000);
622: JVM_HAS_JDK14_TIMESTAMP = t.getTime() == 5;
623: if (JVM_HAS_JDK14_TIMESTAMP) {
624: log.info("using JDK 1.4 java.sql.Timestamp handling");
625: } else {
626: log.info("using pre JDK 1.4 java.sql.Timestamp handling");
627: }
628: }
629:
630: public static BytecodeProvider getBytecodeProvider() {
631: return BYTECODE_PROVIDER_INSTANCE;
632: }
633:
634: /**
635: * Does this JVM have the IBM JDK 1.3.1. The bug is <tt>new Timestamp(x).getTime()!=x</tt>.
636: */
637: public static boolean jvmHasTimestampBug() {
638: return JVM_HAS_TIMESTAMP_BUG;
639: }
640:
641: /**
642: * Does this JVM handle <tt>Timestamp</tt> in the JDK 1.4 compliant way?
643: */
644: public static boolean jvmHasJDK14Timestamp() {
645: return JVM_HAS_JDK14_TIMESTAMP;
646: }
647:
648: /**
649: * Does this JVM support <tt>LinkedHashSet</tt>, <tt>LinkedHashMap</tt>.
650: * @see java.util.LinkedHashSet
651: * @see java.util.LinkedHashMap
652: */
653: public static boolean jvmSupportsLinkedHashCollections() {
654: return JVM_SUPPORTS_LINKED_HASH_COLLECTIONS;
655: }
656:
657: public static boolean jvmSupportsGetGeneratedKeys() {
658: return JVM_SUPPORTS_GET_GENERATED_KEYS;
659: }
660:
661: /**
662: * Should we use streams to bind binary types to JDBC IN parameters.
663: * Property <tt>hibernate.jdbc.use_streams_for_binary</tt>.
664: * @see Environment#USE_STREAMS_FOR_BINARY
665: */
666: public static boolean useStreamsForBinary() {
667: return ENABLE_BINARY_STREAMS;
668: }
669:
670: /**
671: * Should we use CGLIB reflection optimizer.
672: * Property <tt>hibernate.jdbc.use_refection_optimizer</tt>.
673: * @see Environment#USE_REFLECTION_OPTIMIZER
674: */
675: public static boolean useReflectionOptimizer() {
676: return ENABLE_REFLECTION_OPTIMIZER;
677: }
678:
679: private Environment() {
680: throw new UnsupportedOperationException();
681: }
682:
683: /**
684: * Return <tt>System</tt> properties, extended by any properties specified
685: * in <tt>hibernate.properties</tt>.
686: * @return Properties
687: */
688: public static Properties getProperties() {
689: Properties copy = new Properties();
690: copy.putAll(GLOBAL_PROPERTIES);
691: return copy;
692: }
693:
694: /**
695: * Get the name of a JDBC transaction isolation level
696: *
697: * @see java.sql.Connection
698: * @param isolation as defined by <tt>java.sql.Connection</tt>
699: * @return a human-readable name
700: */
701: public static String isolationLevelToString(int isolation) {
702: return (String) ISOLATION_LEVELS.get(new Integer(isolation));
703: }
704:
705: public static BytecodeProvider buildBytecodeProvider(
706: Properties properties) {
707: String provider = PropertiesHelper.getString(
708: Environment.BYTECODE_PROVIDER, properties, "cglib");
709: log.info("Bytecode provider name : " + provider);
710: return buildBytecodeProvider(provider);
711: }
712:
713: private static BytecodeProvider buildBytecodeProvider(
714: String providerName) {
715: if ("javassist".equals(providerName)) {
716: return new org.hibernate.bytecode.javassist.BytecodeProviderImpl();
717: } else if ("cglib".equals(providerName)) {
718: return new org.hibernate.bytecode.cglib.BytecodeProviderImpl();
719: } else {
720: log.warn("unrecognized bytecode provider [" + providerName
721: + "], using cglib by default");
722: return new org.hibernate.bytecode.cglib.BytecodeProviderImpl();
723: }
724: }
725:
726: }
|