1 package org.eclipse.birt.report.data.oda.jdbc;
2
3 import java.sql.DatabaseMetaData;
4 import java.sql.SQLException;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Enumeration;
8 import java.util.HashMap;
9 import java.util.Map;
10 import java.util.Properties;
11 import java.util.logging.Level;
12 import java.util.logging.Logger;
13
14 import org.eclipse.birt.report.data.bidi.utils.core.BidiConstants;
15 import org.eclipse.birt.report.data.bidi.utils.core.BidiFormat;
16 import org.eclipse.birt.report.data.bidi.utils.core.BidiTransform;
17 import org.eclipse.birt.report.data.oda.i18n.ResourceConstants;
18 import org.eclipse.birt.report.data.oda.jdbc.bidi.BidiCallStatement;
19 import org.eclipse.birt.report.data.oda.jdbc.bidi.BidiStatement;
20 import org.eclipse.datatools.connectivity.oda.IConnection;
21 import org.eclipse.datatools.connectivity.oda.IDataSetMetaData;
22 import org.eclipse.datatools.connectivity.oda.IQuery;
23 import org.eclipse.datatools.connectivity.oda.OdaException;
24
25 import com.ibm.icu.util.ULocale;
26 import org.kuali.ole.config.OLEReportDBConfig;
27
28
29
30
31
32
33 public class Connection implements IConnection
34 {
35
36 protected java.sql.Connection jdbcConn = null;
37
38
39 private static Logger logger = Logger.getLogger( Connection.class.getName( ) );
40
41
42 private static final String advancedDataType = "org.eclipse.birt.report.data.oda.jdbc.SPSelectDataSet";
43
44 protected Map appContext;
45
46 private Boolean autoCommit;
47 private int isolationMode = Constants.TRANSCATION_ISOLATION_DEFAULT;
48
49 OLEReportDBConfig oleReportDBConfig = new OLEReportDBConfig();
50
51
52
53 public boolean isOpen( ) throws OdaException
54 {
55 return ( jdbcConn != null );
56 }
57
58
59
60
61 public void open( Properties connProperties ) throws OdaException
62 {
63 if ( this.appContext != null )
64 {
65 Object value = this.appContext.get( IConnectionFactory.PASS_IN_CONNECTION );
66 if ( value != null && ( value instanceof java.sql.Connection ) )
67 {
68 jdbcConn = (java.sql.Connection) value;
69 logger.logp( Level.FINER,
70 Connection.class.getName( ),
71 "open",
72 jdbcConn.toString( ) );
73 return;
74 }
75 }
76 if ( connProperties == null )
77 {
78 IllegalArgumentException e = new IllegalArgumentException( "connProperties cannot be null" );
79 logger.logp( Level.FINE,
80 Connection.class.getName( ),
81 "open",
82 e.getMessage( ),
83 e );
84 throw e;
85 }
86
87 if ( logger.isLoggable( Level.FINE ) )
88 {
89 StringBuffer logMsg = new StringBuffer( "Connection.open(Properties). connProperties = " );
90 for ( Enumeration enumeration = connProperties.propertyNames( ); enumeration.hasMoreElements( ); )
91 {
92 String propName = (String) enumeration.nextElement( );
93
94 String lcPropName = propName.toLowerCase( );
95 String propVal;
96 if ( lcPropName.indexOf( "password" ) >= 0
97 || lcPropName.indexOf( "pwd" ) >= 0 )
98 propVal = "***";
99 else
100 {
101 propVal = connProperties.getProperty( propName );
102 if ( lcPropName.equals( "odaurl" ) )
103 {
104 propVal = LogUtil.encryptURL( propVal );
105 }
106 }
107
108 logMsg.append( propName )
109 .append( "=" ).append( propVal ).append( ";" );
110 }
111 logger.logp( Level.FINE,
112 Connection.class.getName( ),
113 "open",
114 logMsg.toString( ) );
115 }
116
117 close( );
118
119 String dataSource = connProperties.getProperty( Constants.ODADataSource );
120 if ( dataSource != null )
121 {
122
123 UnsupportedOperationException e = new UnsupportedOperationException( "Oda-jdbc:connect by data source" );
124 logger.logp( Level.FINE,
125 Connection.class.getName( ),
126 "open",
127 e.getMessage( ),
128 e );
129 throw e;
130 }
131 else
132 {
133 if (hasBidiProperties (connProperties)){
134 connProperties = bidiTransform (connProperties);
135 }
136 String url = oleReportDBConfig.getPropertyByKey(Constants.REPORT_DBA_URL);
137 String jndiName = connProperties.getProperty( Constants.ODAJndiName );
138
139 String autoCommit = connProperties.getProperty( Constants.CONNECTION_AUTO_COMMIT );
140 if ( autoCommit != null )
141 {
142 this.autoCommit = Boolean.valueOf( autoCommit );
143 }
144
145 String isolationMode = connProperties.getProperty( Constants.CONNECTION_ISOLATION_MODE );
146 this.isolationMode = Constants.getIsolationMode( isolationMode );
147
148 if ( (url == null || url.length( ) == 0) && (jndiName == null ||
149 jndiName.length() == 0) )
150 {
151 throw new JDBCException( ResourceConstants.DRIVER_MISSING_PROPERTIES,
152 ResourceConstants.ERROR_MISSING_PROPERTIES );
153 }
154 connectByUrl( url, connProperties );
155 }
156 logger.log(Level.FINER, "JDBC connection: " + jdbcConn + " is opened");
157 updateAppContext (connProperties);
158 }
159
160 private boolean hasBidiProperties(Properties connProperties) {
161 if ((connProperties.containsKey(BidiConstants.CONTENT_FORMAT_PROP_NAME)) ||
162 (connProperties.containsKey(BidiConstants.METADATA_FORMAT_PROP_NAME)))
163 return true;
164 return false;
165 }
166
167 private void updateAppContext(Properties connProperties) {
168 if (appContext == null)
169 appContext = new HashMap();
170 appContext.put(Constants.CONNECTION_PROPERTIES_STR, connProperties);
171 }
172
173
174
175
176
177 protected void connectByUrl( String url, Properties connProperties )
178 throws OdaException
179 {
180 assert connProperties != null;
181 assert url != null;
182
183
184
185 Properties props = new Properties( );
186 for ( Enumeration enumeration = connProperties.propertyNames( ); enumeration.hasMoreElements( ); )
187 {
188 String propName = (String) enumeration.nextElement( );
189 if ( ! propName.startsWith( "oda" ) && ! propName.startsWith( "Oda" ) )
190 {
191 props.setProperty( propName,
192 connProperties.getProperty( propName ) );
193 }
194 }
195
196
197 String user = oleReportDBConfig.getPropertyByKey(Constants.REPORT_DBA_USERNAME);
198 String pwd = oleReportDBConfig.getPropertyByKey(Constants.REPORT_DBA_PASSWORD);
199 props = JDBCDriverManager.addUserAuthenticationProperties(
200 props, user, pwd );
201
202 String driverClass = oleReportDBConfig.getPropertyByKey(Constants.REPORT_DBA_DRIVER);
203 String jndiNameUrl = connProperties.getProperty( Constants.ODAJndiName );
204
205 try
206 {
207 if ( ( jndiNameUrl == null || jndiNameUrl.trim( ).length( ) == 0 )
208 && ConnectionPoolFactory.getInstance( ) != null )
209 {
210 jdbcConn = ConnectionPoolFactory.getInstance( )
211 .getConnection( driverClass,
212 url,
213 props,
214 getDriverClassPath( ),
215 this.appContext );
216 populateConnectionProp( );
217 logger.log(Level.FINE, "JDBC connection success : " + jdbcConn );
218 }
219 }
220 catch ( Exception e )
221 {
222 if( e instanceof SQLException )
223 {
224 SQLException e1 = (SQLException)e;
225 logger.log( Level.SEVERE,
226 "JDBC connection throws exception: Error Code "
227 + e1.getErrorCode( ) + " Message:"
228 + e1.getLocalizedMessage( ) );
229
230 if( "28000".equals( e1.getSQLState( )))
231 throw new JDBCException( ResourceConstants.CONN_CANNOT_GET, e1 );
232 }
233 else
234 {
235 logger.log( Level.SEVERE, "JDBC connection throws exception: " + e.getLocalizedMessage( ) );
236 }
237 }
238 try
239 {
240
241 if ( jdbcConn == null )
242 {
243 jdbcConn = JDBCDriverManager.getInstance( )
244 .getConnection( driverClass,
245 url,
246 jndiNameUrl,
247 props,
248 getDriverClassPath( ) );
249
250 populateConnectionProp( );
251 }
252 }
253 catch ( SQLException e )
254 {
255 throw new JDBCException( ResourceConstants.CONN_CANNOT_GET, e );
256 }
257 }
258
259 private void populateConnectionProp( ) throws SQLException
260 {
261 if( jdbcConn!= null )
262 {
263 if( this.autoCommit != null )
264 jdbcConn.setAutoCommit( this.autoCommit );
265 else
266 {
267 if (DBConfig.getInstance().qualifyPolicy(
268 jdbcConn.getMetaData().getDriverName(),
269 DBConfig.SET_COMMIT_TO_FALSE) ) {
270 this.autoCommit = false;
271 jdbcConn.setAutoCommit( false );
272 }
273 }
274 if( this.isolationMode!= Constants.TRANSCATION_ISOLATION_DEFAULT)
275 jdbcConn.setTransactionIsolation( this.isolationMode );
276 }
277 }
278
279 @SuppressWarnings("unchecked")
280 protected Collection<String> getDriverClassPath( )
281 {
282 if ( this.appContext == null )
283 return null;
284
285 if ( this.appContext.get( IConnectionFactory.DRIVER_CLASSPATH ) == null )
286 return null;
287
288 Object classPath = this.appContext.get( IConnectionFactory.DRIVER_CLASSPATH );
289
290 if ( classPath instanceof String )
291 {
292 ArrayList<String> result = new ArrayList<String>();
293 result.add( classPath.toString( ) );
294 return result;
295 }
296 else if ( classPath instanceof Collection )
297 {
298 ArrayList<String> result = new ArrayList<String>();
299 for( Object aClassPath: (Collection)classPath )
300 {
301 if( aClassPath!= null )
302 result.add( aClassPath.toString( ) );
303 }
304 return result;
305 }
306
307 return null;
308 }
309
310
311
312
313 public IDataSetMetaData getMetaData( String dataSetType )
314 throws OdaException
315 {
316 logger.logp( Level.FINEST,
317 Connection.class.getName( ),
318 "getMetaData",
319 "Connection.getMetaData(" + dataSetType + ")" );
320
321 DatabaseMetaData dbMetadata = null;
322 if ( jdbcConn != null )
323 {
324 try
325 {
326 dbMetadata = jdbcConn.getMetaData( );
327 }
328 catch ( SQLException e )
329 {
330 throw new JDBCException( ResourceConstants.CONN_CANNOT_GET_METADATA,
331 e );
332 }
333 }
334 return new DataSourceMetaData( this, dbMetadata );
335 }
336
337
338
339
340 public IQuery newQuery( String dataSourceType ) throws OdaException
341 {
342 logger.logp( Level.FINER,
343 Connection.class.getName( ),
344 "createStatement",
345 "Connection.createStatement(" + dataSourceType + ")" );
346
347
348 assertOpened( );
349 if ( dataSourceType != null
350 && dataSourceType.equalsIgnoreCase( advancedDataType ) )
351 return createCallStatement( jdbcConn );
352 else
353 return createStatement( jdbcConn );
354 }
355
356 private IQuery createCallStatement(java.sql.Connection jdbcConn2) throws OdaException {
357 if ((appContext != null) &&
358 (appContext.get(Constants.CONNECTION_PROPERTIES_STR) != null)){
359 Properties props = (Properties)appContext.get(Constants.CONNECTION_PROPERTIES_STR);
360 if (hasBidiProperties(props))
361 return new BidiCallStatement(jdbcConn, props);
362 }
363 return new CallStatement( jdbcConn );
364 }
365
366 protected IQuery createStatement(java.sql.Connection jdbcConn) throws OdaException {
367 if ((appContext != null) &&
368 (appContext.get(Constants.CONNECTION_PROPERTIES_STR) != null)){
369 Properties props = (Properties)appContext.get(Constants.CONNECTION_PROPERTIES_STR);
370 if (hasBidiProperties(props))
371 return new BidiStatement(jdbcConn, props);
372 }
373 return new Statement( jdbcConn );
374 }
375
376
377
378
379 public void commit( ) throws OdaException
380 {
381 logger.logp( Level.FINEST,
382 Connection.class.getName( ),
383 "commit",
384 "Connection.commit()" );
385 assertOpened( );
386 try
387 {
388 jdbcConn.commit( );
389 }
390 catch ( SQLException e )
391 {
392 throw new JDBCException( ResourceConstants.CONN_COMMIT_ERROR, e );
393 }
394 }
395
396
397
398
399 public void rollback( ) throws OdaException
400 {
401 logger.logp( Level.FINEST,
402 Connection.class.getName( ),
403 "rollback",
404 "Connection.rollback()" );
405 assertOpened( );
406 try
407 {
408 jdbcConn.rollback( );
409 }
410 catch ( SQLException e )
411 {
412 throw new JDBCException( ResourceConstants.CONN_ROLLBACK_ERROR, e );
413 }
414 }
415
416
417
418
419 public int getMaxQueries( ) throws OdaException
420 {
421 if ( jdbcConn != null )
422 {
423 try
424 {
425 DatabaseMetaData dbMetadata = jdbcConn.getMetaData( );
426 int maxstmts = dbMetadata.getMaxStatements( );
427 int maxconns = dbMetadata.getMaxConnections( );
428 if ( maxstmts == 0 && maxconns == 0 )
429 return 0;
430 else if ( maxconns == 0 || maxstmts < maxconns )
431 return 1;
432 else
433 return maxstmts / maxconns;
434 }
435 catch ( SQLException e )
436 {
437 return 1;
438 }
439 }
440
441 return 0;
442 }
443
444
445
446
447 public void close( ) throws OdaException
448 {
449 logger.logp( Level.FINEST,
450 Connection.class.getName( ),
451 "close",
452 "Connection closed." );
453 if ( jdbcConn == null )
454 {
455 return;
456 }
457 try
458 {
459 if ( this.appContext != null && jdbcConn != null )
460 {
461 Object option = this.appContext.get( IConnectionFactory.CLOSE_PASS_IN_CONNECTION );
462 boolean closePassInConnection = ( option instanceof Boolean )
463 ? ( (Boolean) option ).booleanValue( ) : true;
464 if ( !closePassInConnection )
465 return;
466 }
467
468 if ( jdbcConn.isClosed( ) == false )
469 {
470 jdbcConn.close( );
471 logger.log(Level.FINE, "JDBC connection: " + jdbcConn + " is closed");
472 }
473 else
474 {
475 logger.log(Level.FINER, "JDBC connection: " + jdbcConn + " is already closed outside of JDBC ODA driver");
476 }
477 }
478 catch ( SQLException e )
479 {
480 try
481 {
482 if (DBConfig.getInstance().qualifyPolicy(
483 jdbcConn.getMetaData().getDriverName(),
484 DBConfig.IGNORE_UNIMPORTANT_EXCEPTION))
485 return;
486 if ( this.autoCommit == Boolean.FALSE && DBConfig.getInstance().qualifyPolicy( jdbcConn.getMetaData().getDriverName(), DBConfig.TRY_COMMIT_THEN_CLOSE ))
487 {
488 jdbcConn.commit();
489 jdbcConn.close();
490 return;
491 }
492 }
493 catch (SQLException e1) {
494
495 }
496 throw new JDBCException( ResourceConstants.CONN_CANNOT_CLOSE, e );
497 }
498 jdbcConn = null;
499 }
500
501
502
503
504 public void setAppContext( Object context ) throws OdaException
505 {
506 if( context instanceof Map )
507 this.appContext = (Map) context;
508 }
509
510
511
512
513
514
515 protected Map<?,?> getAppContextMap()
516 {
517 return this.appContext;
518 }
519
520
521
522
523
524
525 private void assertOpened( ) throws OdaException
526 {
527 if ( jdbcConn == null )
528 {
529 throw new JDBCException( ResourceConstants.DRIVER_NO_CONNECTION,
530 ResourceConstants.ERROR_NO_CONNECTION );
531 }
532 }
533
534
535
536
537 public void setLocale( ULocale locale ) throws OdaException
538 {
539
540 throw new UnsupportedOperationException();
541 }
542
543 private Properties bidiTransform( Properties connectionProperties )
544 {
545 if ( connectionProperties == null )
546 {
547 return null;
548 }
549 Properties p = new Properties( );
550 String metadataBidiFormatStr = connectionProperties.getProperty(BidiConstants.METADATA_FORMAT_PROP_NAME);
551 if (!BidiFormat.isValidBidiFormat(metadataBidiFormatStr))
552 return connectionProperties;
553
554 for ( Enumeration enumeration = connectionProperties.propertyNames( ); enumeration.hasMoreElements( ); )
555 {
556 String propName = (String) enumeration.nextElement( );
557 String propValue = connectionProperties.getProperty( propName );
558 if ( (Constants.ODAUser.equals( propName ) || Constants.ODAPassword.equals( propName ))
559 && propValue != null )
560 {
561 p.put( propName, BidiTransform.transform( propValue, BidiConstants.DEFAULT_BIDI_FORMAT_STR, metadataBidiFormatStr) );
562 }
563 else if (Constants.ODAURL.equals( propName ))
564 {
565 p.put( propName, BidiTransform.transformURL( propValue, BidiConstants.DEFAULT_BIDI_FORMAT_STR, metadataBidiFormatStr) );
566 }
567 else
568 {
569 p.put( propName, propValue );
570 }
571 }
572 return p;
573 }
574
575
576
577
578 public static class Constants
579 {
580 public static final String REPORT_DBA_USERNAME = "report.dba.username";
581 public static final String REPORT_DBA_PASSWORD = "report.dba.password";
582 public static final String REPORT_DBA_DRIVER = "report.dba.driver";
583 public static final String REPORT_DBA_URL = "report.dba.url";
584 public static final String ODAURL = "odaURL";
585 public static final String ODAPassword = "odaPassword";
586 public static final String ODAUser = "odaUser";
587 public static final String ODADriverClass = "odaDriverClass";
588 public static final String ODADataSource = "odaDataSource";
589 public static final String ODAJndiName = "odaJndiName";
590 public static final String CONNECTION_AUTO_COMMIT = "odaAutoCommit";
591 public static final String CONNECTION_ISOLATION_MODE = "odaIsolationMode";
592 public static final int TRANSCATION_ISOLATION_DEFAULT = -1;
593 public static final String TRANSACTION_READ_COMMITTED = "read-committed";
594 public static final String TRANSACTION_READ_UNCOMMITTED = "read-uncommitted";
595 public static final String TRANSACTION_REPEATABLE_READ = "repeatable-read";
596 public static final String TRANSACTION_SERIALIZABLE = "serializable";
597 public static final String CONNECTION_PROPERTIES_STR = "connectionProperties";
598 public static final String ODAResourceIdentiers = "odaResourceIdentifiers";
599
600 public static int getIsolationMode( String value )
601 {
602 if( value == null )
603 return TRANSCATION_ISOLATION_DEFAULT;
604 if( TRANSACTION_READ_COMMITTED.equals( value ))
605 return java.sql.Connection.TRANSACTION_READ_COMMITTED;
606 if( TRANSACTION_READ_UNCOMMITTED.equals( value ))
607 return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
608 if( TRANSACTION_REPEATABLE_READ.equals( value ))
609 return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
610 if( TRANSACTION_SERIALIZABLE.equals( value ))
611 return java.sql.Connection.TRANSACTION_SERIALIZABLE;
612 return Integer.parseInt( value );
613 }
614 }
615
616 }