View Javadoc
1   /**
2    * Copyright 2014 Internet2
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * @author mchyzer
18   * $Id: C3p0JdbcConnectionProvider.java,v 1.2 2008-10-13 08:04:29 mchyzer Exp $
19   */
20  package edu.internet2.middleware.subject.provider;
21  
22  import java.sql.Connection;
23  import java.sql.SQLException;
24  import java.util.Properties;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  import com.mchange.v2.c3p0.ComboPooledDataSource;
31  import com.mchange.v2.c3p0.DataSources;
32  
33  import edu.internet2.middleware.subject.SourceUnavailableException;
34  import edu.internet2.middleware.subject.SubjectUtils;
35  
36  
37  /**
38   *
39   */
40  public class C3p0JdbcConnectionProvider implements JdbcConnectionProvider {
41  
42    /** if the connection should be readonly */
43    private boolean connectionReadOnly;
44  
45    /** combo pooled data source */
46    private ComboPooledDataSource comboPooledDataSource;
47    
48    /** logger */
49    private static Log log = LogFactory.getLog(C3p0JdbcConnectionProvider.class);
50  
51    /**
52     * @see edu.internet2.middleware.subject.provider.JdbcConnectionProvider#connectionBean()
53     */
54    public JdbcConnectionBean connectionBean() throws SQLException {
55      Connection connection = this.comboPooledDataSource.getConnection();
56      connection.setReadOnly(this.connectionReadOnly);
57      return new C3p0JdbcConnectionBean(connection);
58    }
59  
60    /**
61     * bean to hold connection
62     */
63    public static class C3p0JdbcConnectionBean implements JdbcConnectionBean {
64      
65      /** reference to connection */
66      private Connection connection;
67      
68      /**
69       * construct
70       * @param theConnection
71       */
72      public C3p0JdbcConnectionBean(Connection theConnection) {
73        this.connection = theConnection;
74      }
75      /**
76       * @see edu.internet2.middleware.subject.provider.JdbcConnectionBean#connection()
77       */
78      public Connection connection() throws SQLException {
79        return this.connection;
80      }
81      /**
82       * @see edu.internet2.middleware.subject.provider.JdbcConnectionBean#doneWithConnection()
83       */
84      public void doneWithConnection() {
85      }
86      /**
87       * @see edu.internet2.middleware.subject.provider.JdbcConnectionBean#doneWithConnectionError(java.lang.Throwable)
88       */
89      public void doneWithConnectionError(Throwable t) {
90        throw new RuntimeException(t);
91      }
92  
93      /**
94       * @see edu.internet2.middleware.subject.provider.JdbcConnectionBean#doneWithConnectionFinally()
95       */
96      public void doneWithConnectionFinally() {
97        if (this.connection != null) {
98          try {
99            //this doesnt actually close it, just returns to pool
100           this.connection.close();
101         } catch (SQLException ex) {
102           log.info("Error while closing JDBC Connection.", ex);
103         }
104       }
105     }
106     
107   }
108 
109   /**
110    * 
111    * @see java.lang.Object#finalize()
112    */
113   @Override
114   protected void finalize() throws Throwable {
115     super.finalize();
116     DataSources.destroy( this.comboPooledDataSource );
117   }
118 
119   /**
120    * @see edu.internet2.middleware.subject.provider.JdbcConnectionProvider#init(Properties, java.lang.String, java.lang.String, java.lang.Integer, int, java.lang.Integer, int, java.lang.Integer, int, java.lang.String, java.lang.String, java.lang.String, java.lang.Boolean, boolean, String)
121    */
122   public void init(Properties properties, String sourceId, String driver, Integer maxActive, int defaultMaxActive,
123       Integer maxIdle, int defaultMaxIdle, Integer maxWaitSeconds,
124       int defaultMaxWaitSeconds, String dbUrl, String dbUser, String dbPassword,
125       Boolean readOnly, boolean readOnlyDefault, String jdbcConfigId) throws SourceUnavailableException {
126 
127     if (!StringUtils.isBlank(jdbcConfigId)) {
128       throw new RuntimeException("Cannot pass in jdbcConfigId for C3p0JdbcConnectionProvider, its only valid for GrouperJdbcConnectionProvider!");
129     }
130     
131     this.comboPooledDataSource = new ComboPooledDataSource(); 
132     
133     JDBCSourceAdapter.loadDriver(sourceId, driver);
134 
135     ////loads the jdbc driver 
136     //try {
137     //  cpds.setDriverClass(  );
138     //} catch (PropertyVetoException pve) {
139     //  throw new RuntimeException(pve);
140     //}
141     this.comboPooledDataSource.setJdbcUrl( dbUrl ); 
142     this.comboPooledDataSource.setUser(dbUser); 
143     this.comboPooledDataSource.setPassword(dbPassword); 
144     this.comboPooledDataSource.setMaxPoolSize(SubjectUtils.defaultIfNull(maxActive, defaultMaxActive));
145     
146     //this isnt used
147     if (maxIdle != null) {
148       log.warn("maxIdle is not available for c3p0 (in subject API: " + sourceId + ")");
149     }
150     int checkoutTimeout = 1000*SubjectUtils.defaultIfNull(maxWaitSeconds, defaultMaxWaitSeconds);
151     //if checkout timeout is less than 0, then make it 5 minutes
152     checkoutTimeout = checkoutTimeout < 0 ? (5 * 60 * 1000) : checkoutTimeout; 
153     this.comboPooledDataSource.setCheckoutTimeout(checkoutTimeout);
154     this.connectionReadOnly = SubjectUtils.defaultIfNull(readOnly, readOnlyDefault);
155     
156     {
157       //max connection age is if the connection should eventually be thrown out (e.g. for firewalls)
158       String maxConnectionAgeString = properties.getProperty("maxConnectionAge");
159       
160       if (!StringUtils.isBlank(maxConnectionAgeString)) {
161         int maxConnectionAgeInteger = SubjectUtils.intValue(maxConnectionAgeString);
162         this.comboPooledDataSource.setMaxConnectionAge(maxConnectionAgeInteger);
163       }
164     }
165     
166     {
167       //if connections should be tested on checkout
168       String testConnectionOnCheckoutString = properties.getProperty("testConnectionOnCheckout");
169       
170       if (!StringUtils.isBlank(testConnectionOnCheckoutString)) {
171         boolean testConnectionOnCheckout = SubjectUtils.booleanValue(testConnectionOnCheckoutString);
172         this.comboPooledDataSource.setTestConnectionOnCheckout(testConnectionOnCheckout);
173       }
174             
175     }
176     
177     {
178       //test query in database
179       String preferredTestQuery = properties.getProperty("preferredTestQuery");
180       
181       if (!StringUtils.isBlank(preferredTestQuery)) {
182         this.comboPooledDataSource.setPreferredTestQuery(preferredTestQuery);
183       }
184             
185     }
186 
187     
188     {
189       //number of seconds to test connections in pool
190       String idleConnectionTestPeriodString = properties.getProperty("idleConnectionTestPeriod");
191       
192       if (!StringUtils.isBlank(idleConnectionTestPeriodString)) {
193         int idleConnectionTestPeriodInteger = SubjectUtils.intValue(idleConnectionTestPeriodString);
194         this.comboPooledDataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriodInteger);
195       }
196             
197     }
198     
199     
200   }
201 
202   /**
203    * @see edu.internet2.middleware.subject.provider.JdbcConnectionProvider#requiresJdbcConfigInSourcesXml()
204    */
205   public boolean requiresJdbcConfigInSourcesXml() {
206     return true;
207   }
208 
209 }