/* * Copyright (c) JForum Team * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2) Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of "Rafael Steil" nor * the names of its contributors may be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * Created on 02/07/2005 13:18:34 * The JForum Project * http://www.jforum.net */ package net.jforum.dao.mysql.security; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import com.mysql.jdbc.Connection; import com.mysql.jdbc.Statement; import net.jforum.JForumExecutionContext; import net.jforum.dao.generic.security.GenericGroupSecurityDAO; import net.jforum.dao.generic.security.SecurityCommon; import net.jforum.exceptions.DatabaseException; import net.jforum.security.RoleCollection; import net.jforum.util.DbUtils; import net.jforum.util.preferences.SystemGlobals; /** * MySQL 3.23 hacks based on Andy's work * * @author Rafael Steil * @version $Id: MySQL323GroupSecurityDAO.java,v 1.9 2007/08/16 13:07:33 rafaelsteil Exp $ */ public class MySQL323GroupSecurityDAO extends GenericGroupSecurityDAO { /** * @see net.jforum.dao.generic.security.GenericGroupSecurityDAO#loadRoles(int[]) */ protected RoleCollection loadRoles(int[] groupIds) { String groupIdAsString = SecurityCommon.groupIdAsString(groupIds); RoleCollection roleCollection = new RoleCollection(); PreparedStatement rolesP = null; PreparedStatement roleValuesP = null; ResultSet roles = null; ResultSet roleValues = null; try { // Roles String sql = this.sqlWithGroups("PermissionControl.getRoles", groupIdAsString); rolesP = JForumExecutionContext.getConnection().prepareStatement(sql); roles = rolesP.executeQuery(); // RoleValues sql = this.sqlWithGroups("PermissionControl.getRoleValues", groupIdAsString); roleValuesP = JForumExecutionContext.getConnection().prepareStatement(sql); roleValues = roleValuesP.executeQuery(); MySQL323RoleResultSet mergedRs = new MySQL323RoleResultSet(0, 0, null, null); mergedRs.merge(roles, roleValues); roleCollection = SecurityCommon.loadRoles(mergedRs); } catch (Exception e) { throw new DatabaseException(e); } finally { DbUtils.close(roles, rolesP); DbUtils.close(roleValues, roleValuesP); } return roleCollection; } private String sqlWithGroups(String queryName, String groups) { String sql = SystemGlobals.getSql(queryName); if ("".equals(groups)) { // We suppose there is no "negative" group ids sql = sql.replaceAll("#IN#", "-1"); } else { sql = sql.replaceAll("#IN#", groups); } return sql.replaceAll("#IN#", groups); } /** * @see net.jforum.dao.security.SecurityDAO#deleteAllRoles(int) */ public void deleteAllRoles(int id) { PreparedStatement p = null; try { // First, get the set of role ids p = JForumExecutionContext.getConnection().prepareStatement( SystemGlobals.getSql("PermissionControl.getRoleIdsByGroup")); p.setInt(1, id); String roleIds = this.getCsvIdList(p); p.close(); if (roleIds.length() > 0) { // Then remove all matching values p = this.getStatementForCsv(SystemGlobals.getSql("PermissionControl.deleteRoleValuesByRoleId"), roleIds); p.executeUpdate(); p.close(); } // Now delete the group roles p = JForumExecutionContext.getConnection().prepareStatement( SystemGlobals.getSql("PermissionControl.deleteAllGroupRoles")); p.setInt(1, id); p.executeUpdate(); } catch (SQLException e) { throw new DatabaseException(e); } finally { DbUtils.close(p); } } /** * Gets a statement to use with some csv data * * @param sql The SQL query to execute. It must have an "?", which will be replaced by * <code>csv</code> * @param csv The ids to replace * @return The statement, ready to execute * @throws SQLException */ protected PreparedStatement getStatementForCsv(String sql, String csv) throws SQLException { int index = sql.indexOf('?'); sql = sql.substring(0, index) + csv + sql.substring(index + 1); return JForumExecutionContext.getConnection().prepareStatement(sql); } /** * Gets a set of ids from a statement The statement is expected to return an id in the first * column * * @param p The statement to execute * @return The ids, separated by comma * @throws SQLException */ protected String getCsvIdList(PreparedStatement p) throws SQLException { ResultSet rs = p.executeQuery(); StringBuffer sb = new StringBuffer(); while (rs.next()) { sb.append(rs.getInt(1)).append(","); } sb.append("-1"); rs.close(); return sb.toString(); } private static class MySQL323RoleResultSet extends com.mysql.jdbc.ResultSet { private Map currentEntry; private Iterator dataIterator; private List data = new ArrayList(); public MySQL323RoleResultSet(long updateCount, long updateId, Connection connection, Statement statement) { super(updateCount, updateId, connection, statement); } public void merge(ResultSet roles, ResultSet roleValues) throws SQLException { this.fillDataFromRs(roles); this.fillDataFromRs(roleValues); this.dataIterator = this.data.iterator(); } private void fillDataFromRs(ResultSet rs) throws SQLException { while (rs.next()) { Map m = new HashMap(); m.put("name", rs.getString("name")); m.put("role_value", rs.getString("role_value")); this.data.add(m); } } /** * @see com.mysql.jdbc.ResultSet#next() */ public boolean next() throws SQLException { boolean hasNext = this.dataIterator.hasNext(); if (hasNext) { this.currentEntry = (Map)this.dataIterator.next(); } return hasNext; } /** * @see com.mysql.jdbc.ResultSet#getString(java.lang.String) */ public String getString(String column) throws SQLException { return (String)this.currentEntry.get(column); } /** * Always returns false */ public boolean wasNull() throws SQLException { return false; } /** * Does nothing */ public void close() throws SQLException {} } }