001: /*
002: * Copyright (c) JForum Team
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms,
006: * with or without modification, are permitted provided
007: * that the following conditions are met:
008: *
009: * 1) Redistributions of source code must retain the above
010: * copyright notice, this list of conditions and the
011: * following disclaimer.
012: * 2) Redistributions in binary form must reproduce the
013: * above copyright notice, this list of conditions and
014: * the following disclaimer in the documentation and/or
015: * other materials provided with the distribution.
016: * 3) Neither the name of "Rafael Steil" nor
017: * the names of its contributors may be used to endorse
018: * or promote products derived from this software without
019: * specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
022: * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
023: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
024: * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
025: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR
026: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
027: * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
028: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
029: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES
030: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
031: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
032: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
033: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
034: * IN CONTRACT, STRICT LIABILITY, OR TORT
035: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
036: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
037: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
038: *
039: * Created on 02/07/2005 13:18:34
040: * The JForum Project
041: * http://www.jforum.net
042: */
043: package net.jforum.dao.mysql.security;
044:
045: import java.sql.PreparedStatement;
046: import java.sql.ResultSet;
047: import java.sql.SQLException;
048: import java.util.ArrayList;
049: import java.util.HashMap;
050: import java.util.Iterator;
051: import java.util.List;
052: import java.util.Map;
053:
054: import com.mysql.jdbc.Connection;
055: import com.mysql.jdbc.Statement;
056:
057: import net.jforum.JForumExecutionContext;
058: import net.jforum.dao.generic.security.GenericGroupSecurityDAO;
059: import net.jforum.dao.generic.security.SecurityCommon;
060: import net.jforum.exceptions.DatabaseException;
061: import net.jforum.security.RoleCollection;
062: import net.jforum.util.DbUtils;
063: import net.jforum.util.preferences.SystemGlobals;
064:
065: /**
066: * MySQL 3.23 hacks based on Andy's work
067: *
068: * @author Rafael Steil
069: * @version $Id: MySQL323GroupSecurityDAO.java,v 1.9 2007/08/16 13:07:33 rafaelsteil Exp $
070: */
071: public class MySQL323GroupSecurityDAO extends GenericGroupSecurityDAO {
072: /**
073: * @see net.jforum.dao.generic.security.GenericGroupSecurityDAO#loadRoles(int[])
074: */
075: protected RoleCollection loadRoles(int[] groupIds) {
076: String groupIdAsString = SecurityCommon
077: .groupIdAsString(groupIds);
078:
079: RoleCollection roleCollection = new RoleCollection();
080:
081: PreparedStatement rolesP = null;
082: PreparedStatement roleValuesP = null;
083: ResultSet roles = null;
084: ResultSet roleValues = null;
085:
086: try {
087: // Roles
088: String sql = this .sqlWithGroups(
089: "PermissionControl.getRoles", groupIdAsString);
090:
091: rolesP = JForumExecutionContext.getConnection()
092: .prepareStatement(sql);
093: roles = rolesP.executeQuery();
094:
095: // RoleValues
096: sql = this .sqlWithGroups("PermissionControl.getRoleValues",
097: groupIdAsString);
098:
099: roleValuesP = JForumExecutionContext.getConnection()
100: .prepareStatement(sql);
101: roleValues = roleValuesP.executeQuery();
102:
103: MySQL323RoleResultSet mergedRs = new MySQL323RoleResultSet(
104: 0, 0, null, null);
105: mergedRs.merge(roles, roleValues);
106:
107: roleCollection = SecurityCommon.loadRoles(mergedRs);
108: } catch (Exception e) {
109: throw new DatabaseException(e);
110: } finally {
111: DbUtils.close(roles, rolesP);
112: DbUtils.close(roleValues, roleValuesP);
113: }
114:
115: return roleCollection;
116: }
117:
118: private String sqlWithGroups(String queryName, String groups) {
119: String sql = SystemGlobals.getSql(queryName);
120:
121: if ("".equals(groups)) {
122: // We suppose there is no "negative" group ids
123: sql = sql.replaceAll("#IN#", "-1");
124: } else {
125: sql = sql.replaceAll("#IN#", groups);
126: }
127:
128: return sql.replaceAll("#IN#", groups);
129: }
130:
131: /**
132: * @see net.jforum.dao.security.SecurityDAO#deleteAllRoles(int)
133: */
134: public void deleteAllRoles(int id) {
135: PreparedStatement p = null;
136: try {
137: // First, get the set of role ids
138: p = JForumExecutionContext
139: .getConnection()
140: .prepareStatement(
141: SystemGlobals
142: .getSql("PermissionControl.getRoleIdsByGroup"));
143: p.setInt(1, id);
144:
145: String roleIds = this .getCsvIdList(p);
146:
147: p.close();
148:
149: if (roleIds.length() > 0) {
150: // Then remove all matching values
151: p = this
152: .getStatementForCsv(
153: SystemGlobals
154: .getSql("PermissionControl.deleteRoleValuesByRoleId"),
155: roleIds);
156: p.executeUpdate();
157: p.close();
158: }
159:
160: // Now delete the group roles
161: p = JForumExecutionContext
162: .getConnection()
163: .prepareStatement(
164: SystemGlobals
165: .getSql("PermissionControl.deleteAllGroupRoles"));
166: p.setInt(1, id);
167: p.executeUpdate();
168: } catch (SQLException e) {
169: throw new DatabaseException(e);
170: } finally {
171: DbUtils.close(p);
172: }
173: }
174:
175: /**
176: * Gets a statement to use with some csv data
177: *
178: * @param sql The SQL query to execute. It must have an "?", which will be replaced by
179: * <code>csv</code>
180: * @param csv The ids to replace
181: * @return The statement, ready to execute
182: * @throws SQLException
183: */
184: protected PreparedStatement getStatementForCsv(String sql,
185: String csv) throws SQLException {
186: int index = sql.indexOf('?');
187: sql = sql.substring(0, index) + csv + sql.substring(index + 1);
188: return JForumExecutionContext.getConnection().prepareStatement(
189: sql);
190: }
191:
192: /**
193: * Gets a set of ids from a statement The statement is expected to return an id in the first
194: * column
195: *
196: * @param p The statement to execute
197: * @return The ids, separated by comma
198: * @throws SQLException
199: */
200: protected String getCsvIdList(PreparedStatement p)
201: throws SQLException {
202: ResultSet rs = p.executeQuery();
203:
204: StringBuffer sb = new StringBuffer();
205:
206: while (rs.next()) {
207: sb.append(rs.getInt(1)).append(",");
208: }
209:
210: sb.append("-1");
211:
212: rs.close();
213:
214: return sb.toString();
215: }
216:
217: private static class MySQL323RoleResultSet extends
218: com.mysql.jdbc.ResultSet {
219: private Map currentEntry;
220: private Iterator dataIterator;
221: private List data = new ArrayList();
222:
223: public MySQL323RoleResultSet(long updateCount, long updateId,
224: Connection connection, Statement statement) {
225: super (updateCount, updateId, connection, statement);
226: }
227:
228: public void merge(ResultSet roles, ResultSet roleValues)
229: throws SQLException {
230: this .fillDataFromRs(roles);
231: this .fillDataFromRs(roleValues);
232:
233: this .dataIterator = this .data.iterator();
234: }
235:
236: private void fillDataFromRs(ResultSet rs) throws SQLException {
237: while (rs.next()) {
238: Map m = new HashMap();
239:
240: m.put("name", rs.getString("name"));
241: m.put("role_value", rs.getString("role_value"));
242:
243: this .data.add(m);
244: }
245: }
246:
247: /**
248: * @see com.mysql.jdbc.ResultSet#next()
249: */
250: public boolean next() throws SQLException {
251: boolean hasNext = this .dataIterator.hasNext();
252:
253: if (hasNext) {
254: this .currentEntry = (Map) this .dataIterator.next();
255: }
256:
257: return hasNext;
258: }
259:
260: /**
261: * @see com.mysql.jdbc.ResultSet#getString(java.lang.String)
262: */
263: public String getString(String column) throws SQLException {
264: return (String) this .currentEntry.get(column);
265: }
266:
267: /**
268: * Always returns false
269: */
270: public boolean wasNull() throws SQLException {
271: return false;
272: }
273:
274: /**
275: * Does nothing
276: */
277: public void close() throws SQLException {
278: }
279: }
280: }
|