001 /*
002 * $Id: JDBCLoginService.java 3100 2008-10-14 22:33:10Z rah003 $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021 package org.jdesktop.swingx.auth;
022 import java.sql.Connection;
023 import java.sql.DriverManager;
024 import java.util.Properties;
025 import java.util.logging.Level;
026 import java.util.logging.Logger;
027
028 import javax.naming.InitialContext;
029 /**
030 * A login service for connecting to SQL based databases via JDBC
031 *
032 * @author rbair
033 */
034 public class JDBCLoginService extends LoginService {
035 private static final Logger LOG = Logger.getLogger(JDBCLoginService.class
036 .getName());
037
038 /**
039 * The connection to the database
040 */
041 private Connection conn;
042 /**
043 * If used, defines the JNDI context from which to get a connection to
044 * the data base
045 */
046 private String jndiContext;
047 /**
048 * When using the DriverManager to connect to the database, this specifies
049 * any additional properties to use when connecting.
050 */
051 private Properties properties;
052
053 /**
054 * Create a new JDBCLoginService and initializes it to connect to a
055 * database using the given params.
056 * @param driver
057 * @param url
058 */
059 public JDBCLoginService(String driver, String url) {
060 super(url);
061 try {
062 Class.forName(driver);
063 } catch (Exception e) {
064 LOG.log(Level.WARNING, "The driver passed to the " +
065 "JDBCLoginService constructor could not be loaded. " +
066 "This may be due to the driver not being on the classpath", e);
067 }
068 this.setUrl(url);
069 }
070
071 /**
072 * Create a new JDBCLoginService and initializes it to connect to a
073 * database using the given params.
074 * @param driver
075 * @param url
076 * @param props
077 */
078 public JDBCLoginService(String driver, String url, Properties props) {
079 super(url);
080 try {
081 Class.forName(driver);
082 } catch (Exception e) {
083 LOG.log(Level.WARNING, "The driver passed to the " +
084 "JDBCLoginService constructor could not be loaded. " +
085 "This may be due to the driver not being on the classpath", e);
086 }
087 this.setUrl(url);
088 this.setProperties(props);
089 }
090
091 /**
092 * Create a new JDBCLoginService and initializes it to connect to a
093 * database using the given params.
094 * @param jndiContext
095 */
096 public JDBCLoginService(String jndiContext) {
097 super(jndiContext);
098 this.jndiContext = jndiContext;
099 }
100
101 /**
102 * Default JavaBean constructor
103 */
104 public JDBCLoginService() {
105 super();
106 }
107
108 /**
109 * @return the JDBC connection url
110 */
111 public String getUrl() {
112 return getServer();
113 }
114
115 /**
116 * @param url set the JDBC connection url
117 */
118 public void setUrl(String url) {
119 String old = getUrl();
120 setServer(url);
121 firePropertyChange("url", old, getUrl());
122 }
123
124 /**
125 * @return JDBC connection properties
126 */
127 public Properties getProperties() {
128 return properties;
129 }
130
131 /**
132 * @param properties miscellaneous JDBC properties to use when connecting
133 * to the database via the JDBC driver
134 */
135 public void setProperties(Properties properties) {
136 Properties old = getProperties();
137 this.properties = properties;
138 firePropertyChange("properties", old, getProperties());
139 }
140
141 public Connection getConnection() {
142 return conn;
143 }
144
145 public void setConnection(Connection conn) {
146 Connection old = getConnection();
147 this.conn = conn;
148 firePropertyChange("connection", old, getConnection());
149 }
150
151 /**
152 * Attempts to get a JDBC Connection from a JNDI javax.sql.DataSource, using
153 * that connection for interacting with the database.
154 * @throws Exception
155 */
156 private void connectByJNDI(String userName, char[] password) throws Exception {
157 InitialContext ctx = new InitialContext();
158 javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup(jndiContext);
159 conn = ds.getConnection(userName, new String(password));
160 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
161 }
162
163 /**
164 * Attempts to get a JDBC Connection from a DriverManager. If properties
165 * is not null, it tries to connect with those properties. If that fails,
166 * it then attempts to connect with a user name and password. If that fails,
167 * it attempts to connect without any credentials at all.
168 * <p>
169 * If, on the other hand, properties is null, it first attempts to connect
170 * with a username and password. Failing that, it tries to connect without
171 * any credentials at all.
172 * @throws Exception
173 */
174 private void connectByDriverManager(String userName, char[] password) throws Exception {
175 if (getProperties() != null) {
176 try {
177 conn = DriverManager.getConnection(getUrl(), getProperties());
178 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
179 } catch (Exception e) {
180 try {
181 conn = DriverManager.getConnection(getUrl(), userName, new String(password));
182 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
183 } catch (Exception ex) {
184 conn = DriverManager.getConnection(getUrl());
185 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
186 }
187 }
188 } else {
189 try {
190 conn = DriverManager.getConnection(getUrl(), userName, new String(password));
191 } catch (Exception e) {
192 LOG.log(Level.WARNING, "Connection with properties failed. " +
193 "Tryint to connect without.", e);
194 //try to connect without using the userName and password
195 conn = DriverManager.getConnection(getUrl());
196
197 }
198 }
199 }
200
201 /**
202 * @param name user name
203 * @param password user password
204 * @param server Must be either a valid JDBC URL for the type of JDBC driver you are using,
205 * or must be a valid JNDIContext from which to get the database connection
206 */
207 public boolean authenticate(String name, char[] password, String server) throws Exception {
208 //try to form a connection. If it works, conn will not be null
209 //if the jndiContext is not null, then try to get the DataSource to use
210 //from jndi
211 if (jndiContext != null) {
212 try {
213 connectByJNDI(name, password);
214 } catch (Exception e) {
215 try {
216 connectByDriverManager(name, password);
217 } catch (Exception ex) {
218 LOG.log(Level.WARNING, "Login failed", ex);
219 //login failed
220 return false;
221 }
222 }
223 } else {
224 try {
225 connectByDriverManager(name, password);
226 } catch (Exception ex) {
227 LOG.log(Level.WARNING, "", ex);
228 return false;
229 }
230 }
231 return true;
232 }
233 }