View Javadoc

1   /*
2   jGuard is a security framework based on top of jaas (java authentication and authorization security).
3   it is written for web applications, to resolve simply, access control problems.
4   version $Name$
5   http://sourceforge.net/projects/jguard/
6   
7   Copyright (C) 2004  Charles GAY
8   
9   This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13  
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  Lesser General Public License for more details.
18  
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23  
24  jGuard project home page:
25  http://sourceforge.net/projects/jguard/
26  
27  */
28  
29  package net.sf.jguard.ext.database;
30  
31  import java.sql.Connection;
32  import java.sql.SQLException;
33  import java.util.HashMap;
34  import java.util.Hashtable;
35  import java.util.Map;
36  
37  import java.util.logging.Level;
38  import javax.naming.InitialContext;
39  import javax.naming.NamingException;
40  import javax.sql.DataSource;
41  import net.sf.jguard.ext.SecurityConstants;
42  import org.apache.commons.dbcp.BasicDataSource;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  
47  
48  /**
49   * Factory for Database Connection.
50   * @author <a href="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
51   * @version $Revision: 2976 $
52   */
53  public final class ConnectionFactory  {
54  	/** Logger for this class */
55  	private static final Logger logger = LoggerFactory.getLogger(ConnectionFactory.class.getName());
56  
57      private  String driverClassName = null;
58      private  String url = null;
59      private  String login = null;
60      private  String password = null;
61  
62      /**
63       * key string which contains applicationName, and, if this application is "secured" (in a jGuard notion),
64       * "|" and the applicationPassword
65       */
66      private  String key = null;
67      
68      private short mode = 0;
69      private final static short DRIVER=0;
70      private final static short JNDI=1;
71      private final static short DATASOURCE=2;
72      //Map which contains Datasources ans connection informations
73      //(when the connection is reach through the driverManager)
74      private  Map connMap = new HashMap();
75      private  DataSource datasource = null;
76  
77      
78      /**
79       * inject the Datasource with this constructor.
80       * that's the IoC way.
81       */
82      public ConnectionFactory(DataSource dataSource){
83          this.datasource = dataSource;
84          mode = ConnectionFactory.DATASOURCE;
85      }
86      
87      /**
88       * initialise connection settings for the specified webapp in the map (with the <strong>applicationName</strong> parameter).
89       * @param opts
90       */
91      public ConnectionFactory(Map opts){
92  
93      	logger.debug(" ConnectionFactoryOptions="+opts);
94  
95          
96          //JNDI way
97          String jndiRef = (String)opts.get("JNDI");
98          if (jndiRef!= null){
99  
100            try {
101               Hashtable env = new Hashtable(opts);
102               InitialContext initCtx = new InitialContext(env);
103               Object object = (DataSource) initCtx.lookup(jndiRef);
104                if (object instanceof DataSource) {
105 				datasource= (DataSource) object;
106 				}else{
107 					throw new IllegalArgumentException(" JNDI lookup "+jndiRef+" must return an object of type javax.sql.DataSource ");
108 				}
109               connMap.put(key,datasource);
110               mode= ConnectionFactory.JNDI;
111            } catch (NamingException e) {
112 				if (logger.isDebugEnabled()) {
113 					logger.debug("init() -  datasource cannot be retrieved through JNDI "
114                     + e.getMessage());
115 				}
116            }catch(Throwable t){
117         	   System.out.println(t.getMessage());
118            }
119 
120         }else{
121             //DriverManager way
122             driverClassName = (String)opts.get(SecurityConstants.DATABASE_DRIVER);
123             url =  (String)opts.get(SecurityConstants.DATABASE_DRIVER_URL);
124             login = (String)opts.get(SecurityConstants.DATABASE_DRIVER_LOGIN);
125             password = (String)opts.get(SecurityConstants.DATABASE_DRIVER_PASSWORD);
126             if(password==null){
127                 password="";
128             }
129             datasource = getDataSource(driverClassName,url,login,password,opts);
130             
131             mode= ConnectionFactory.DRIVER;
132         }
133 
134     }
135 
136     /**
137      * Returns a database connection.
138      * Connection is pooled with DBCP when url,driver,login and password are set;
139      *otherwise, datasource is grabbed either with the injected Datasource (passe in the constructor),
140      *or via JNDI where the application server should have  pooled it.
141      * @return java.sql.Connection obtained either from a pool or explicitly
142      */
143     public Connection getConnection()   {
144         Connection conn = null;
145 
146         //jndi stuff
147         if(mode==ConnectionFactory.JNDI){
148           conn = getConnectionWithDataSource();
149         //driver manager stuff
150         }else if(mode == ConnectionFactory.DATASOURCE){
151             conn = getConnectionWithDataSource();
152         }else{
153             conn = getConnectionWithDriver();
154         }
155         return conn;
156 
157 
158     }
159 
160 
161    
162 
163     /**
164      * get a connection grabbed through a Datasource reached by JNDI.
165      * @see javax.sql.DataSource
166      * @return Connection
167      */
168 	private  Connection getConnectionWithDataSource() {
169 		Connection conn = null;
170           try {
171               conn = datasource.getConnection();
172           } catch (SQLException e) {
173 					logger.error("getConnection() - connection through JNDI cannot be established "
174 					+ e.getMessage());
175 				
176           }
177 		return conn;
178 	}
179 
180 	/**
181 	 * get a connection (pooled with DBCP) with some DriverManager parameters.
182 	 * @see java.sql.Driver
183 	 * @return Connection
184 	 */
185 	private Connection getConnectionWithDriver() {
186 		Connection conn = null;
187 		try {
188                         conn = datasource.getConnection();
189 			
190 		}catch (SQLException e) {
191 					logger.error("getConnection() - SQLException "+ e.getMessage());
192 					logger.error("getConnection() - SQLException state="+ e.getSQLState());
193 					logger.error("getConnection() - SQLException error code="+ e.getErrorCode());
194 					logger.error("getConnection() - SQLException error next exception="+ e.getNextException());
195 					logger.error("getConnection(String, boolean)", e);
196 		}
197 		return conn;
198 	}
199 
200 	
201     private DataSource getDataSource(String driverClassName,String url, String login, String password,Map options) {
202         //DBCP pooled Datasource
203         BasicDataSource ds = new BasicDataSource();
204         ds.setDriverClassName(driverClassName);
205         ds.setUsername(login);
206         ds.setPassword(password);
207         ds.setUrl(url);
208         
209         if(!options.containsKey(DBCPUtils.DEFAULT_AUTO_COMMIT)){
210     		options.put(DBCPUtils.DEFAULT_AUTO_COMMIT, "true");
211     	}
212         //set DBCP-related properties
213         DBCPUtils.setDatasourceProperties(ds,options);
214         
215         return ds;
216     }
217 
218 
219 }