001 /*
002 * $Id: JDBCLoginService.java,v 1.6 2005/11/11 23:05:15 rbair Exp $
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 * @return the JDBC connection url
103 */
104 public String getUrl() {
105 return getServer();
106 }
107
108 /**
109 * @param url set the JDBC connection url
110 */
111 public void setUrl(String url) {
112 setServer(url);
113 }
114
115 /**
116 * @return JDBC connection properties
117 */
118 public Properties getProperties() {
119 return properties;
120 }
121
122 /**
123 * @param properties miscellaneous JDBC properties to use when connecting
124 * to the database via the JDBC driver
125 */
126 public void setProperties(Properties properties) {
127 this.properties = properties;
128 }
129
130 public Connection getConnection() {
131 return conn;
132 }
133
134 /**
135 * Attempts to get a JDBC Connection from a JNDI javax.sql.DataSource, using
136 * that connection for interacting with the database.
137 * @throws Exception
138 */
139 private void connectByJNDI(String userName, char[] password) throws Exception {
140 InitialContext ctx = new InitialContext();
141 javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup(jndiContext);
142 conn = ds.getConnection(userName, new String(password));
143 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
144 }
145
146 /**
147 * Attempts to get a JDBC Connection from a DriverManager. If properties
148 * is not null, it tries to connect with those properties. If that fails,
149 * it then attempts to connect with a user name and password. If that fails,
150 * it attempts to connect without any credentials at all.
151 * <p>
152 * If, on the other hand, properties is null, it first attempts to connect
153 * with a username and password. Failing that, it tries to connect without
154 * any credentials at all.
155 * @throws Exception
156 */
157 private void connectByDriverManager(String userName, char[] password) throws Exception {
158 if (getProperties() != null) {
159 try {
160 conn = DriverManager.getConnection(getUrl(), getProperties());
161 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
162 } catch (Exception e) {
163 try {
164 conn = DriverManager.getConnection(getUrl(), userName, new String(password));
165 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
166 } catch (Exception ex) {
167 conn = DriverManager.getConnection(getUrl());
168 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
169 }
170 }
171 } else {
172 try {
173 conn = DriverManager.getConnection(getUrl(), userName, new String(password));
174 } catch (Exception e) {
175 LOG.log(Level.WARNING, "Connection with properties failed. " +
176 "Tryint to connect without.", e);
177 //try to connect without using the userName and password
178 conn = DriverManager.getConnection(getUrl());
179
180 }
181 }
182 }
183
184 /**
185 * @param name user name
186 * @param password user password
187 * @param server Must be either a valid JDBC URL for the type of JDBC driver you are using,
188 * or must be a valid JNDIContext from which to get the database connection
189 */
190 public boolean authenticate(String name, char[] password, String server) throws Exception {
191 //try to form a connection. If it works, conn will not be null
192 //if the jndiContext is not null, then try to get the DataSource to use
193 //from jndi
194 if (jndiContext != null) {
195 try {
196 connectByJNDI(name, password);
197 } catch (Exception e) {
198 try {
199 connectByDriverManager(name, password);
200 } catch (Exception ex) {
201 LOG.log(Level.WARNING, "Login failed", ex);
202 //login failed
203 return false;
204 }
205 }
206 } else {
207 try {
208 connectByDriverManager(name, password);
209 } catch (Exception ex) {
210 LOG.log(Level.WARNING, "", ex);
211 return false;
212 }
213 }
214 return true;
215 }
216 }