001/* 002 * $Id: JDBCLoginService.java 4147 2012-02-01 17:13:24Z kschaefe $ 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 */ 021package org.jdesktop.swingx.auth; 022import java.sql.Connection; 023import java.sql.DriverManager; 024import java.util.Properties; 025import java.util.logging.Level; 026import java.util.logging.Logger; 027 028import javax.naming.InitialContext; 029 030import org.jdesktop.beans.JavaBean; 031/** 032 * A login service for connecting to SQL based databases via JDBC 033 * 034 * @author rbair 035 */ 036@JavaBean 037public class JDBCLoginService extends LoginService { 038 private static final Logger LOG = Logger.getLogger(JDBCLoginService.class 039 .getName()); 040 041 /** 042 * The connection to the database 043 */ 044 private Connection conn; 045 /** 046 * If used, defines the JNDI context from which to get a connection to 047 * the data base 048 */ 049 private String jndiContext; 050 /** 051 * When using the DriverManager to connect to the database, this specifies 052 * any additional properties to use when connecting. 053 */ 054 private Properties properties; 055 056 /** 057 * Create a new JDBCLoginService and initializes it to connect to a 058 * database using the given params. 059 * @param driver 060 * @param url 061 */ 062 public JDBCLoginService(String driver, String url) { 063 super(url); 064 try { 065 Class.forName(driver); 066 } catch (Exception e) { 067 LOG.log(Level.WARNING, "The driver passed to the " + 068 "JDBCLoginService constructor could not be loaded. " + 069 "This may be due to the driver not being on the classpath", e); 070 } 071 this.setUrl(url); 072 } 073 074 /** 075 * Create a new JDBCLoginService and initializes it to connect to a 076 * database using the given params. 077 * @param driver 078 * @param url 079 * @param props 080 */ 081 public JDBCLoginService(String driver, String url, Properties props) { 082 super(url); 083 try { 084 Class.forName(driver); 085 } catch (Exception e) { 086 LOG.log(Level.WARNING, "The driver passed to the " + 087 "JDBCLoginService constructor could not be loaded. " + 088 "This may be due to the driver not being on the classpath", e); 089 } 090 this.setUrl(url); 091 this.setProperties(props); 092 } 093 094 /** 095 * Create a new JDBCLoginService and initializes it to connect to a 096 * database using the given params. 097 * @param jndiContext 098 */ 099 public JDBCLoginService(String jndiContext) { 100 super(jndiContext); 101 this.jndiContext = jndiContext; 102 } 103 104 /** 105 * Default JavaBean constructor 106 */ 107 public JDBCLoginService() { 108 super(); 109 } 110 111 /** 112 * @return the JDBC connection url 113 */ 114 public String getUrl() { 115 return getServer(); 116 } 117 118 /** 119 * @param url set the JDBC connection url 120 */ 121 public void setUrl(String url) { 122 String old = getUrl(); 123 setServer(url); 124 firePropertyChange("url", old, getUrl()); 125 } 126 127 /** 128 * @return JDBC connection properties 129 */ 130 public Properties getProperties() { 131 return properties; 132 } 133 134 /** 135 * @param properties miscellaneous JDBC properties to use when connecting 136 * to the database via the JDBC driver 137 */ 138 public void setProperties(Properties properties) { 139 Properties old = getProperties(); 140 this.properties = properties; 141 firePropertyChange("properties", old, getProperties()); 142 } 143 144 public Connection getConnection() { 145 return conn; 146 } 147 148 public void setConnection(Connection conn) { 149 Connection old = getConnection(); 150 this.conn = conn; 151 firePropertyChange("connection", old, getConnection()); 152 } 153 154 /** 155 * Attempts to get a JDBC Connection from a JNDI javax.sql.DataSource, using 156 * that connection for interacting with the database. 157 * @throws Exception 158 */ 159 private void connectByJNDI(String userName, char[] password) throws Exception { 160 InitialContext ctx = new InitialContext(); 161 javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup(jndiContext); 162 conn = ds.getConnection(userName, new String(password)); 163 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); 164 } 165 166 /** 167 * Attempts to get a JDBC Connection from a DriverManager. If properties 168 * is not null, it tries to connect with those properties. If that fails, 169 * it then attempts to connect with a user name and password. If that fails, 170 * it attempts to connect without any credentials at all. 171 * <p> 172 * If, on the other hand, properties is null, it first attempts to connect 173 * with a username and password. Failing that, it tries to connect without 174 * any credentials at all. 175 * @throws Exception 176 */ 177 private void connectByDriverManager(String userName, char[] password) throws Exception { 178 if (getProperties() != null) { 179 try { 180 conn = DriverManager.getConnection(getUrl(), getProperties()); 181 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); 182 } catch (Exception e) { 183 try { 184 conn = DriverManager.getConnection(getUrl(), userName, new String(password)); 185 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); 186 } catch (Exception ex) { 187 conn = DriverManager.getConnection(getUrl()); 188 conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); 189 } 190 } 191 } else { 192 try { 193 conn = DriverManager.getConnection(getUrl(), userName, new String(password)); 194 } catch (Exception e) { 195 LOG.log(Level.WARNING, "Connection with properties failed. " + 196 "Tryint to connect without.", e); 197 //try to connect without using the userName and password 198 conn = DriverManager.getConnection(getUrl()); 199 200 } 201 } 202 } 203 204 /** 205 * @param name user name 206 * @param password user password 207 * @param server Must be either a valid JDBC URL for the type of JDBC driver you are using, 208 * or must be a valid JNDIContext from which to get the database connection 209 */ 210 @Override 211 public boolean authenticate(String name, char[] password, String server) throws Exception { 212 //try to form a connection. If it works, conn will not be null 213 //if the jndiContext is not null, then try to get the DataSource to use 214 //from jndi 215 if (jndiContext != null) { 216 try { 217 connectByJNDI(name, password); 218 } catch (Exception e) { 219 try { 220 connectByDriverManager(name, password); 221 } catch (Exception ex) { 222 LOG.log(Level.WARNING, "Login failed", ex); 223 //login failed 224 return false; 225 } 226 } 227 } else { 228 try { 229 connectByDriverManager(name, password); 230 } catch (Exception ex) { 231 LOG.log(Level.WARNING, "", ex); 232 return false; 233 } 234 } 235 return true; 236 } 237}