/* * © Copyright IBM Corp. 2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.sbt.security.credential.store; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import com.ibm.commons.runtime.Application; import com.ibm.commons.util.StringUtil; public class DBCredentialStore extends BaseStore{ private final String DEFAULT_JNDINAME = "jdbc/ibmsbt-dbtokenstore"; private final String DEFAULT_DB_TABLE = "SBTKREP"; static final String sourceClass = DBCredentialStore.class.getName(); static final Logger logger = Logger.getLogger(sourceClass); private static boolean driverLoaded; /* * Properties to access the underlying db repository. * If jdbc url is provided application will use that, otherwise jndi * If none of these properties is set, application would try with default jndi */ private String jdbcUrl; private String jndiName; private String tableName; private String jdbcDriverClass; public DBCredentialStore() { tableName = DEFAULT_DB_TABLE; } @Override public Object load(String service, String type, String user) throws CredentialStoreException { return getFromDB(service, type, user); } @Override public void store(String service, String type, String user, Object credentials) throws CredentialStoreException { storeInDB(service,type,user,credentials); } @Override public void remove(String service, String type, String user) throws CredentialStoreException { removeFromDB(service, type, user); } /* * Fetch the consumer token from DB */ private Object getFromDB(String serviceName, String type, String user) throws CredentialStoreException { String application = findApplicationName(); if(StringUtil.isEmpty(user)){ // User id could be null for consumer tokens user = ""; } try { Connection connection = getConnection(); try { PreparedStatement stmt = connection .prepareStatement("SELECT CREDENTIALTOKEN FROM "+getTableName()+" WHERE APPID = ? AND SERVICENAME = ? and TYPE = ? AND USERID = ?"); try { stmt.setString(1, application); stmt.setString(2, serviceName); stmt.setString(3, type); stmt.setString(4, user); ResultSet rs = stmt.executeQuery(); try { if(rs.next()){ byte[] buf = rs.getBytes(1); return(deSerialize(buf)); } } finally { rs.close(); } } finally { stmt.close(); } } finally { connection.close(); } } catch (SQLException e) { logger.log(Level.SEVERE, "getAppToken : ", e); throw new CredentialStoreException(e, "DBCredentialStore.java : getAppToken caused a SQLException"); } return null; } /* * Insert app token */ private void storeInDB(String serviceName, String type, String user, Object token) throws CredentialStoreException { try { Connection connection = getConnection(); try { String application = findApplicationName(); if(StringUtil.isEmpty(user)){ user = ""; } PreparedStatement ps = connection.prepareStatement("INSERT INTO "+getTableName()+" VALUES (?, ?, ?, ?, ?)"); try { byte[] apptoken = serialize(token); ps.setString(1, application); ps.setString(2, serviceName); ps.setObject(3, type); ps.setObject(4, user); ps.setObject(5, apptoken); ps.executeUpdate(); } finally { ps.close(); } } finally { connection.close(); } } catch (SQLException e) { logger.log(Level.SEVERE, "setAppToken : ", e); throw new CredentialStoreException(e, "DBTokenStore.java : setAppToken caused a SQLException"); } } /* * Delete user token */ private void removeFromDB(String serviceName, String type, String userId) throws CredentialStoreException { try { Connection connection = getConnection(); try { String application = findApplicationName(); if(StringUtil.isEmpty(userId)){ userId = ""; } PreparedStatement ps = connection .prepareStatement("DELETE FROM "+getTableName()+" WHERE APPID = ? AND SERVICENAME = ? AND USERID = ? AND TYPE = ?"); try { ps.setString(1, application); ps.setString(2, serviceName); ps.setString(3, userId); ps.setString(4, type); ps.executeUpdate(); } finally { ps.close(); } } finally { connection.close(); } } catch (SQLException e) { logger.log(Level.SEVERE, "deleteConsumerToken : ", e); throw new CredentialStoreException(e, "DBTokenStore.java : deleteConsumerToken caused a SQLException"); } } /* * Load the DB Drivers */ private synchronized void loadDBDriver() throws CredentialStoreException { if (driverLoaded) { return; } String driver = getJdbcDriverClass(); if(StringUtil.isNotEmpty(driver)){ try { if(Application.getUnchecked()!=null){ Application.getUnchecked().getClassLoader().loadClass(driver); //Class.forname does not work on OSGI }else{ Class.forName(driver).newInstance(); // Load driver } driverLoaded = true; } catch (Exception ex) { driverLoaded = false; logger.log(Level.SEVERE, "loadDBDriver : Could not load driver for class" + driver, ex); throw new CredentialStoreException(ex,"DBCredentialStore.java : loadDBDriver Could not load driver for class" + driver ); } }else{ logger.log(Level.SEVERE, "loadDBDriver : Could not find driver details"); throw new CredentialStoreException(new Exception("DBCredentialStore.java : loadDBDriver Driver not found")); } } /* * Method decides if Connection should be fetched through URL or JNDI */ private Connection getConnection() throws CredentialStoreException{ if(StringUtil.isNotEmpty(getJdbcUrl())){ try { loadDBDriver(); return DriverManager.getConnection(getJdbcUrl()); } catch (Exception e) { logger.log(Level.SEVERE, "DBTokenStore.java : getConnection() : ", e); throw new CredentialStoreException(e,"Problem occured in getting connection using JDBC" ); } }else { return getConnectionUsingJNDI(); } } /* * Read the database settings from JNDI */ private Connection getConnectionUsingJNDI() throws CredentialStoreException { try { String jndikey = getJndiName(); InitialContext initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); if(StringUtil.isEmpty(getJndiName())){ logger.log(Level.INFO, "DBTokenStore.java : getConnectionUsingJNDI : JNDI Key was blank in bean using the default"); jndikey = DEFAULT_JNDINAME; } DataSource ds = (DataSource) envCtx.lookup(jndikey); return ds.getConnection(); } catch (Exception e) { logger.log(Level.SEVERE, "DBTokenStore.java : getConnectionUsingJNDI : ", e); throw new CredentialStoreException(e,"Problem occured in getting connection using JNDI" ); } } public String getJndiName() { return jndiName; } public void setJndiName(String jndiName) { this.jndiName = jndiName; } public String getJdbcDriverClass() { return jdbcDriverClass; } public void setJdbcDriverClass(String jdbcDriverClass) { this.jdbcDriverClass = jdbcDriverClass; } public String getJdbcUrl() { return jdbcUrl; } public void setJdbcUrl(String jdbcUrl) { this.jdbcUrl = jdbcUrl; } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } }