/* * JBoss, Home of Professional Open Source * * Copyright 2013 Red Hat, Inc. and/or its affiliates. * * 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 org.picketlink.idm.jdbc.internal.model.db; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import org.picketlink.common.util.Base64; import org.picketlink.idm.IDMMessages; import org.picketlink.idm.model.Attribute; /** * Storage utility for attributes * * @author Anil Saldhana * @since October 25, 2013 */ public class AttributeStorageUtil extends AbstractStorageUtil { /** * Get the {@link Attribute} given its name and an id * * @param dataSource * @param id * @param attributeName * @return */ public Attribute getAttribute(DataSource dataSource, String id, String attributeName) { if (dataSource == null) { throw IDMMessages.MESSAGES.nullArgument("datasource"); } Attribute attribute = null; Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); String sql = "select attributeType from Attributes where owner =? and name=?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, id); preparedStatement.setString(2, attributeName); resultSet = preparedStatement.executeQuery(); String attributeType = null; while (resultSet.next()) { attributeType = resultSet.getString(1); break; } List<? extends Serializable> valList = getAttributeValues(dataSource, id, attributeName); if (valList.size() > 1) { attribute = new Attribute(attributeName, "dummy"); if (isPrimitiveNativeType(attributeType)) { handlePrimitiveAttributeType(attribute, attributeType, valList); } else { // Multi valued attribute Serializable[] serialArray = new Serializable[valList.size()]; int i = 0; for (Serializable attributeValue : valList) { serialArray[i++] = attributeValue; } attribute.setValue(serialArray); } } else { attribute = new Attribute(attributeName, valList.get(0)); } return attribute; } catch (SQLException e) { throw new RuntimeException(e); } finally { safeClose(resultSet); safeClose(preparedStatement); safeClose(connection); } } /** * Get a list of {@link Attribute} for an identity type * * @param dataSource * @param ownerId * @return */ public List<Attribute> getAttributes(DataSource dataSource, String ownerId) { if (dataSource == null) { throw IDMMessages.MESSAGES.nullArgument("datasource"); } List<Attribute> attributes = new ArrayList<Attribute>(); UserStorageUtil userStorageUtil = new UserStorageUtil(); RoleStorageUtil roleStorageUtil = new RoleStorageUtil(); GroupStorageUtil groupStorageUtil = new GroupStorageUtil(); Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); String sql = "select name,value from Attributes where owner =?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, ownerId); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { String storedName = resultSet.getString(1); Attribute attribute = getAttribute(dataSource, ownerId, storedName); attributes.add(attribute); } } catch (SQLException e) { throw new RuntimeException(e); } finally { safeClose(resultSet); safeClose(preparedStatement); safeClose(connection); } return attributes; } /** * Set the {@link Attribute} for an {@link org.picketlink.idm.model.IdentityType} * * @param dataSource * @param ownerId * @param attribute */ public void setAttribute(DataSource dataSource, String ownerId, Attribute attribute) { if (dataSource == null) { throw IDMMessages.MESSAGES.nullArgument("datasource"); } Object values = attribute.getValue(); if (!values.getClass().isArray()) { Serializable serializedValues = (Serializable) values; values = new Serializable[] { serializedValues }; } if (values instanceof byte[]) { Serializable serializedValues = (Serializable) values; values = new Serializable[] { serializedValues }; } for (Serializable attributeValue : (Serializable[]) values) { UserStorageUtil userStorageUtil = new UserStorageUtil(); RoleStorageUtil roleStorageUtil = new RoleStorageUtil(); GroupStorageUtil groupStorageUtil = new GroupStorageUtil(); Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); String sql = "insert into Attributes set owner =?, name=?, value=?,attributeType=?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, ownerId); preparedStatement.setString(2, attribute.getName()); preparedStatement.setString(3, Base64.encodeObject(attributeValue)); preparedStatement.setString(4, attributeValue.getClass().getName()); int result = preparedStatement.executeUpdate(); if (result == 0) { throw new RuntimeException("Update failed"); } } catch (SQLException e) { throw new RuntimeException(e); } finally { safeClose(resultSet); safeClose(preparedStatement); safeClose(connection); } } } /** * Delete an {@link Attribute} given its name and owner * * @param dataSource * @param ownerId * @param attributeName */ public void deleteAttribute(DataSource dataSource, String ownerId, String attributeName) { if (dataSource == null) { throw IDMMessages.MESSAGES.nullArgument("datasource"); } Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); String sql = "Delete from Attributes where owner =? and name=?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, ownerId); preparedStatement.setString(2, attributeName); int result = preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { safeClose(resultSet); safeClose(preparedStatement); safeClose(connection); } } private List<? extends Serializable> getAttributeValues(DataSource dataSource, String ownerId, String attributeName) { if (dataSource == null) { throw IDMMessages.MESSAGES.nullArgument("datasource"); } List<Serializable> list = new ArrayList<Serializable>(); List<String> stringList = new ArrayList<String>(); Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); String sql = "select value,attributeType from Attributes where owner =? and name=?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, ownerId); preparedStatement.setString(2, attributeName); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { String attributeType = resultSet.getString(2); if (attributeType.equals(String.class.getName())) { stringList.add((String) Base64.decodeToObject(resultSet.getString(1))); } else { list.add((Serializable) Base64.decodeToObject(resultSet.getString(1))); } } } catch (SQLException e) { throw new RuntimeException(e); } finally { safeClose(resultSet); safeClose(preparedStatement); safeClose(connection); } if (stringList.isEmpty() == false) { return stringList; } return list; } private boolean isPrimitiveNativeType(String attributeType) { if (String.class.getName().equals(attributeType) || Integer.class.getName().equals(attributeType)) { return true; } return false; } private void handlePrimitiveAttributeType(Attribute attribute, String attributeType, List<? extends Serializable> valueList) { if (String.class.getName().equals(attributeType)) { // We have a string array String[] serialArray = new String[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = str.toString(); } attribute.setValue(serialArray); } else if (Integer.class.getName().equals(attributeType)) { Integer[] serialArray = new Integer[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = (Integer) str; } attribute.setValue(serialArray); } else if (Long.class.getName().equals(attributeType)) { Long[] serialArray = new Long[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = (Long) str; } attribute.setValue(serialArray); } else if (Double.class.getName().equals(attributeType)) { Double[] serialArray = new Double[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = (Double) str; } attribute.setValue(serialArray); } else if (Float.class.getName().equals(attributeType)) { Float[] serialArray = new Float[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = (Float) str; } attribute.setValue(serialArray); } else if (Short.class.getName().equals(attributeType)) { Short[] serialArray = new Short[valueList.size()]; int i = 0; for (Serializable str : valueList) { serialArray[i++] = (Short) str; } attribute.setValue(serialArray); } } }