Java tutorial
/** * Licensed to Apereo under one or more contributor license * agreements. See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Apereo licenses this file to you 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 the following location: * * 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 org.apereo.services.persondir.support.jdbc; import org.apereo.services.persondir.IPersonAttributes; import org.apereo.services.persondir.support.AbstractDefaultAttributePersonAttributeDao; import org.apereo.services.persondir.support.CaseInsensitiveNamedPersonImpl; import org.apereo.services.persondir.support.IUsernameAttributeProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Required; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.namedparam.AbstractSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Implementation of PersonAttributeDao based on Spring's {@link NamedParameterJdbcTemplate}. * Specify any valid SQL, using named parameters as necessary. Name the columns you want as * attributes with the property 'userAttributeNames' (you can adjust names to taste using * aliases in your SQL). Supports multi-valued attributes through inner joins. * * <p>Example SQL: SELECT USER_ID FROM UP_USER WHERE USER_NAME = :username</p> * * <p>Example Sprring Configuration:</p> * * <bean id="rolesUserSource" class="org.jasig.services.persondir.support.jdbc.NamedParameterJdbcPersonAttributeDao"> * <property name="dataSource" ref="PersonDB" /> * <property name="sql"> * <value> * SELECT rolename AS scsRoleName * from s_external_role * where oprid = UPPER(:username) * </value> * </property> * <property name="usernameAttributeProvider" ref="usernameAttributeProvider" /> * <property name="userAttributeNames"> * <set> * <value>scsRoleName</value> * </set> * </property> * </bean> * * @author drew wills */ public class NamedParameterJdbcPersonAttributeDao extends AbstractDefaultAttributePersonAttributeDao implements InitializingBean { // Instance Members private NamedParameterJdbcTemplate jdbcTemplate; /* * Spring-Configured Dependencies */ private DataSource dataSource; private String sql; private IUsernameAttributeProvider usernameAttributeProvider; private Set<String> availableQueryAttributes = null; // default private Set<String> userAttributeNames = null; // default @Required public void setDataSource(final DataSource dataSource) { this.dataSource = dataSource; } @Required public void setSql(final String sql) { this.sql = sql; } @Override @Required public void setUsernameAttributeProvider(final IUsernameAttributeProvider usernameAttributeProvider) { this.usernameAttributeProvider = usernameAttributeProvider; } public void setAvailableQueryAttributes(final Set<String> availableQueryAttributes) { this.availableQueryAttributes = Collections.unmodifiableSet(availableQueryAttributes); } @Required public void setUserAttributeNames(final Set<String> userAttributeNames) { this.userAttributeNames = Collections.unmodifiableSet(userAttributeNames); } @Override public void afterPropertiesSet() throws Exception { jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } /* * IPersonAttributeDao Implementation */ @Override public Set<String> getAvailableQueryAttributes() { return availableQueryAttributes; } @Override public Set<IPersonAttributes> getPeopleWithMultivaluedAttributes( final Map<String, List<Object>> queryParameters) { final String username = usernameAttributeProvider.getUsernameFromQuery(queryParameters); final RowCallbackHandlerImpl rslt = new RowCallbackHandlerImpl(username); jdbcTemplate.query(sql, new SqlParameterSourceImpl(queryParameters), rslt); return rslt.getResults(); } @Override public Set<String> getPossibleUserAttributeNames() { return userAttributeNames; } /* * Nested Types */ private static final class SqlParameterSourceImpl extends AbstractSqlParameterSource { // Instance Members. private final Map<String, List<Object>> queryParameters; public SqlParameterSourceImpl(final Map<String, List<Object>> queryParameters) { this.queryParameters = queryParameters; } @Override public Object getValue(final String paramName) throws IllegalArgumentException { // Use the first one final List<Object> val = queryParameters.get(paramName); return val != null && val.size() != 0 ? val.get(0) : null; } @Override public boolean hasValue(final String paramName) { final List<Object> val = queryParameters.get(paramName); return val != null && val.size() != 0; } } private class RowCallbackHandlerImpl implements RowCallbackHandler { // Instance Members final String username; final Map<String, Set<Object>> attributes = new HashMap<>(); public RowCallbackHandlerImpl(final String username) { this.username = username; } @Override public void processRow(final ResultSet rs) throws SQLException { for (final String attrName : userAttributeNames) { Set<Object> values = attributes.get(attrName); if (values == null) { values = new HashSet<>(); attributes.put(attrName, values); } final Object val = rs.getObject(attrName); if (val != null) { values.add(val); } } } public Set<IPersonAttributes> getResults() { final Map<String, List<Object>> mapOfLists = new HashMap<>(); for (final Map.Entry<String, Set<Object>> y : attributes.entrySet()) { mapOfLists.put(y.getKey(), new ArrayList<>(y.getValue())); } final IPersonAttributes person = new CaseInsensitiveNamedPersonImpl(username, mapOfLists); return Collections.singleton(person); } } }