fully implemented conference membership management and delete conference -

now almost all the conference functionality is in place
This commit is contained in:
Eric J. Bowersox
2001-02-15 04:28:00 +00:00
parent 0070e4fb44
commit 36f7c7f10f
28 changed files with 1978 additions and 146 deletions

View File

@@ -0,0 +1,101 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.util;
import java.util.Vector;
public class ParallelRunQueue implements Runnable
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Thread[] thrds;
private Vector queue;
private int priority;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public ParallelRunQueue(int nthread)
{
thrds = new Thread[nthread];
for (int i=0; i<nthread; i++)
thrds[i] = null;
queue = new Vector();
priority = Thread.currentThread().getPriority();
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface Runnable
*--------------------------------------------------------------------------------
*/
public void run()
{
while (queue.size()>0)
{ // unqueue a new Runnable
Runnable r = (Runnable)(queue.remove(0));
for (int i=0; i<thrds.length; i++)
{ // scan through our threads list...
if ((thrds[i]==null) || !(thrds[i].isAlive()))
{ // a worker thread is available - start it running
thrds[i] = new Thread(r);
thrds[i].setPriority(priority);
thrds[i].start();
return;
} // end if
} // end for
r.run(); // if all else fails, run it ourselves
} // end while
} // end run
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void queue(Runnable r)
{
for (int i=0; i<thrds.length; i++)
{ // scan through our threads list...
if ((thrds[i]==null) || !(thrds[i].isAlive()))
{ // a worker thread is available - start it running
thrds[i] = new Thread(r);
thrds[i].setPriority(priority);
thrds[i].start();
return;
} // end if
} // end for
queue.add(r); // if all else fails, queue it up
} // end queue
} // end class ParallelRunQueue

View File

@@ -84,6 +84,8 @@ public interface ConferenceContext
public abstract void removeAlias(String alias) throws DataException, AccessError;
public abstract void setMembership(int uid, int grant_level) throws DataException, AccessError;
public abstract void addMember(int uid, boolean as_host) throws DataException, AccessError;
public abstract void removeMember(int uid) throws DataException, AccessError;
@@ -117,18 +119,26 @@ public interface ConferenceContext
public abstract HTMLChecker getNewTopicPreviewChecker();
public abstract void fixSeen() throws DataException;
public abstract void fixSeen() throws DataException, AccessError;
public abstract List getActivePosters(int skip, int limit) throws DataException;
public abstract List getActivePosters(int skip, int limit) throws DataException, AccessError;
public abstract List getActivePosters(int limit) throws DataException;
public abstract List getActivePosters(int limit) throws DataException, AccessError;
public abstract List getActivePosters() throws DataException;
public abstract List getActivePosters() throws DataException, AccessError;
public abstract List getActiveReaders(int skip, int limit) throws DataException;
public abstract List getActiveReaders(int skip, int limit) throws DataException, AccessError;
public abstract List getActiveReaders(int limit) throws DataException;
public abstract List getActiveReaders(int limit) throws DataException, AccessError;
public abstract List getActiveReaders() throws DataException;
public abstract List getActiveReaders() throws DataException, AccessError;
public abstract List getMemberList() throws DataException, AccessError;
public abstract int getMemberLevel(int uid) throws DataException, AccessError;
public abstract void delete() throws DataException, AccessError;
public abstract boolean canDeleteConference();
} // end interface ConferenceContext

View File

@@ -7,7 +7,7 @@
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
@@ -21,7 +21,7 @@ import java.util.BitSet;
import java.util.Date;
import java.util.List;
public interface SIGContext
public interface SIGContext extends SearchMode
{
public static final int HIDE_NONE = 0;
public static final int HIDE_DIRECTORY = 1;
@@ -144,4 +144,11 @@ public interface SIGContext
public abstract boolean canCreateConference();
public abstract List searchForMembers(int field, int mode, String term, int offset, int count)
throws DataException;
public abstract int getSearchMemberCount(int field, int mode, String term) throws DataException;
public abstract List getMemberList() throws DataException;
} // end interface SIGContext

View File

@@ -37,4 +37,6 @@ public interface UserFound
public abstract int getLevel();
public abstract UserFound createNewLevel(int level);
} // end interface UserFound

View File

@@ -67,4 +67,8 @@ public interface VeniceEngine extends SearchMode
public abstract int getNumOldPostsBeforeNew();
public abstract int getMaxNumConferenceMembersDisplay();
public abstract int getMaxNumSIGMembersDisplay();
} // end interface VeniceEngine

View File

@@ -0,0 +1,131 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.core.impl;
import java.sql.*;
import org.apache.log4j.*;
import com.silverwrist.util.ParallelRunQueue;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.core.InternalStateError;
class BackgroundConferencePurge implements Runnable
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(BackgroundConferencePurge.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DataPool datapool;
private int confid;
private int num_topics;
private int max_topicid;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
BackgroundConferencePurge(DataPool datapool, int confid, int num_topics, int max_topicid)
{
this.datapool = datapool;
this.confid = confid;
this.num_topics = num_topics;
this.max_topicid = max_topicid;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface Runnable
*--------------------------------------------------------------------------------
*/
public void run()
{
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge running on conference #" + confid);
Connection conn = null; // pooled database connection
ParallelRunQueue rq = new ParallelRunQueue(2);
try
{ // get a database connection from the pool
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// purge out some auxiliary tables first
stmt.executeUpdate("DELETE FROM confmember WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confsettings WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confhotlist WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confbozo WHERE confid = " + confid + ";");
// look up all the topic IDs that are present in this conference
int[] topicids = new int[num_topics];
StringBuffer sql = new StringBuffer("SELECT topicid FROM topics WHERE confid = ");
sql.append(confid).append(" AND topicid <= ").append(max_topicid).append(" ORDER BY topicid;");
ResultSet rs = stmt.executeQuery(sql.toString());
int topics = 0;
while (rs.next())
topicids[topics++] = rs.getInt(1);
for (int i=0; i<topics; i++)
{ // delete the topic header and settings rows first
stmt.executeUpdate("DELETE FROM topics WHERE topicid = " + topicids[i] + ";");
stmt.executeUpdate("DELETE FROM topicsettings WHERE topicid = " + topicids[i] + ";");
// figure out how many posts are in this topic and create a BackgroundTopicPurge.
sql.setLength(0);
sql.append("SELECT COUNT(*), MAX(postid) FROM posts WHERE topicid = ").append(topicids[i]).append(';');
rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("BackgroundConferencePurge.run screwup on post SELECT");
rq.queue(new BackgroundTopicPurge(datapool,topicids[i],rs.getInt(1),rs.getLong(2)));
} // end for
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge basic delete complete for conf #" + confid);
} // end try
catch (SQLException e)
{ // on an error, just die
logger.error("BackgroundConferencePurge FATAL EXCEPTION purging #" + confid + ": " + e.getMessage(),e);
return;
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
rq.run(); // now run the parallel queue to finish processing
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge COMPLETE for conf #" + confid);
} // end run
} // end class BackgroundConferencePurge

View File

@@ -57,6 +57,7 @@ class ConferenceCoreData implements ConferenceData
private String description; // the conference's description
private String cached_alias = null; // the cached alias (for getAnAlias)
private boolean creating_topic = false; // is somebody creating a topic?
private boolean deleted = false; // has this conference been deleted?
/*--------------------------------------------------------------------------------
* Constructors
@@ -66,7 +67,7 @@ class ConferenceCoreData implements ConferenceData
ConferenceCoreData(EngineBackend engine, DataPool datapool, int confid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("new ConferenceCoreData for conference " + String.valueOf(confid));
logger.debug("new ConferenceCoreData for conference " + confid);
this.engine = engine;
this.datapool = datapool;
this.confid = confid;
@@ -83,7 +84,7 @@ class ConferenceCoreData implements ConferenceData
sql.append(confid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new DataException("Conference #" + String.valueOf(confid) + " does not exist in the database.");
throw new DataException("Conference #" + confid + " does not exist in the database.");
loadData(rs); // load the conference data
@@ -107,7 +108,7 @@ class ConferenceCoreData implements ConferenceData
boolean pvt, String name, String descr)
{
if (logger.isDebugEnabled())
logger.debug("new ConferenceCoreData for NEW conference " + String.valueOf(confid));
logger.debug("new ConferenceCoreData for NEW conference " + confid);
this.engine = engine;
this.datapool = datapool;
this.confid = confid;
@@ -221,6 +222,9 @@ class ConferenceCoreData implements ConferenceData
public List getAliases() throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null;
Vector rc = new Vector();
@@ -258,6 +262,9 @@ class ConferenceCoreData implements ConferenceData
public List getHosts() throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null;
Vector rc = new Vector();
@@ -304,24 +311,32 @@ class ConferenceCoreData implements ConferenceData
public boolean canReadConference(int level)
{
if (deleted)
return false;
return (level>=read_level);
} // end canReadConference
public boolean canPostToConference(int level)
{
if (deleted)
return false;
return (level>=post_level);
} // end canReadConference
public boolean canCreateTopic(int level)
{
if (deleted)
return false;
return (level>=create_level);
} // end canCreateTopic
public boolean canChangeConference(int level)
{
if (deleted)
return false;
return (level>=change_level);
} // end canChangeConference
@@ -371,6 +386,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setSecurityLevels(SIGBackend sig, int read, int post, int create, int hide,
int nuke, int change, int delete) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -402,7 +420,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record reflecting the change
ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid));
"conf=" + confid);
} // end try
catch (SQLException e)
@@ -434,6 +452,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setName(SIGBackend sig, String val) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -457,7 +478,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record reflecting the change
ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid));
"conf=" + confid);
} // end try
catch (SQLException e)
@@ -489,6 +510,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setDescription(String val) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
try
@@ -526,6 +550,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void addAlias(SIGBackend sig, String alias) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -566,7 +593,7 @@ class ConferenceCoreData implements ConferenceData
// set the database's update date and generate a new audit record
touchUpdate(conn);
ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"add=" + alias);
"conf=" + confid,"add=" + alias);
} // end try
catch (SQLException e)
@@ -598,6 +625,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void removeAlias(SIGBackend sig, String alias) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -651,7 +681,7 @@ class ConferenceCoreData implements ConferenceData
if ((cached_alias!=null) && cached_alias.equals(alias))
cached_alias = null; // also release the cached alias and force a re-get
ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"remove=" + alias);
"conf=" + confid,"remove=" + alias);
} // end if
@@ -685,6 +715,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setMembership(SIGBackend sig, int uid, int grant_level) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -742,8 +775,7 @@ class ConferenceCoreData implements ConferenceData
{ // set the database's update date and generate a new audit record
touchUpdate(conn);
ar = new AuditRecord(AuditRecord.CONF_MEMBERSHIP,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"uid=" + String.valueOf(uid),
"level=" + String.valueOf(grant_level));
"conf=" + confid,"uid=" + uid,"level=" + grant_level);
} // end if
@@ -777,12 +809,17 @@ class ConferenceCoreData implements ConferenceData
public boolean canHideTopics(int level)
{
if (deleted)
return false;
return (level>=hide_level);
} // end canHideTopics
public synchronized String getAnAlias() throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
if (cached_alias!=null)
return cached_alias;
@@ -821,6 +858,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud,
String body, int body_lines) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
short new_topic_num; // sequential number of the new topic
@@ -891,8 +931,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.CREATE_TOPIC,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + String.valueOf(confid),"num=" + String.valueOf(new_topic_num),
"title=" + title);
"confid=" + confid,"num=" + new_topic_num,"title=" + title);
} // end try
finally
@@ -935,18 +974,25 @@ class ConferenceCoreData implements ConferenceData
public boolean canScribblePosts(int level)
{
if (deleted)
return false;
return (level>=nuke_level);
} // end canScribblePosts
public boolean canNukePosts(int level)
{
if (deleted)
return false;
return (level>=nuke_level);
} // end canNukePosts
public synchronized void touchUpdate(Connection conn, java.util.Date date) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
try
{ // update the last update date
Statement stmt = conn.createStatement();
@@ -998,6 +1044,207 @@ class ConferenceCoreData implements ConferenceData
} // end getTopTopic
public List getMemberList() throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
if (logger.isDebugEnabled())
logger.debug("Member list: conference = " + confid);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, confmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.confid = ");
sql.append(confid).append(" AND u.is_anon = 0 ORDER BY u.username;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end getMemberList
public int getMemberLevel(int uid) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create the statement
StringBuffer sql = new StringBuffer("SELECT granted_lvl FROM confmember WHERE confid = ");
sql.append(confid).append(" AND uid = ").append(uid).append(';');
// execute the statement and return the retrieved value
ResultSet rs = stmt.executeQuery(sql.toString());
if (rs.next())
return rs.getInt(1);
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return -1; // default return if no member level present
} // end getMemberLevel
public boolean isDeleted()
{
return deleted;
} // end isDeleted
public boolean canDeleteConference(int level)
{
if (deleted)
return false;
return (level>=delete_level);
} // end canDeleteConference
public synchronized void delete(SIGBackend sig) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
int topic_count, topic_max; // count and maximum topic
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// lock tables on the critical stuff that MUST be deleted now
stmt.executeUpdate("LOCK TABLES confs WRITE, confalias WRITE, topics READ;");
try
{ // first delete the conference record itself
StringBuffer sql = new StringBuffer("DELETE FROM confs WHERE confid = ");
sql.append(confid).append(';');
stmt.executeUpdate(sql.toString());
// now delete all its alias records
sql.setLength(0);
sql.append("DELETE FROM confalias WHERE confid = ").append(confid).append(';');
stmt.executeUpdate(sql.toString());
// determine the number of topics in this conference, and the maximum topic ID
sql.setLength(0);
sql.append("SELECT COUNT(*), MAX(topicid) FROM topics WHERE confid = ").append(confid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("ConferenceCoreData.delete screwup on topic SELECT");
topic_count = rs.getInt(1);
topic_max = rs.getInt(2);
// record that we're now deleted
create_date = null;
last_update = null;
top_topic = -1;
name = null;
description = null;
cached_alias = null;
deleted = true;
} // end try
finally
{ // unlock the tables before we go
Statement ulk_stmt = conn.createStatement();
ulk_stmt.executeUpdate("UNLOCK TABLES;");
} // end finally
// create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.DELETE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + confid);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("DB error deleting conference: " + e.getMessage(),e);
throw new DataException("unable to delete conference: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
try
{ // save off the audit record before we go, though
if ((ar!=null) && (conn!=null))
ar.store(conn);
} // end try
catch (SQLException e)
{ // we couldn't store the audit record!
logger.error("DB error saving audit record: " + e.getMessage(),e);
} // end catch
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
// Delete the rest of the gunk in the background; spin off another thread to handle it.
BackgroundConferencePurge purger = new BackgroundConferencePurge(datapool,confid,topic_count,topic_max);
Thread thrd = new Thread(purger);
thrd.setPriority(Thread.NORM_PRIORITY-1);
thrd.start();
} // end delete
/*--------------------------------------------------------------------------------
* External static operations (usable only from within package)
*--------------------------------------------------------------------------------
@@ -1100,13 +1347,13 @@ class ConferenceCoreData implements ConferenceData
// create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.CREATE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + String.valueOf(new_confid),"name=" + name,"alias=" + alias);
"confid=" + new_confid,"name=" + name,"alias=" + alias);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("DB error creating SIG: " + e.getMessage(),e);
throw new DataException("unable to create SIG: " + e.getMessage(),e);
logger.error("DB error creating conference: " + e.getMessage(),e);
throw new DataException("unable to create conference: " + e.getMessage(),e);
} // end catch
finally

View File

@@ -7,7 +7,7 @@
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
@@ -92,4 +92,14 @@ public interface ConferenceData extends ReferencedData
public abstract short getTopTopic();
public abstract List getMemberList() throws DataException;
public abstract int getMemberLevel(int uid) throws DataException;
public abstract boolean isDeleted();
public abstract boolean canDeleteConference(int level);
public abstract void delete(SIGBackend sig) throws DataException;
} // end interface ConferenceData

View File

@@ -7,7 +7,7 @@
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
@@ -100,4 +100,12 @@ public interface ConferenceSIGContext extends ReferencedData
public abstract short getTopTopic();
public abstract List getMemberList() throws DataException;
public abstract int getMemberLevel(int uid) throws DataException;
public abstract boolean canDeleteConference(int level);
public abstract void delete(SIGBackend sig) throws DataException;
} // end interface ConferenceSIGContext

View File

@@ -88,6 +88,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
private boolean hide_list; // hide the conference in the list?
private ConfCache cache; // cache of locally-important information
private ConferenceData confdata = null; // the inner conference data object
private boolean deleted = false; // has this conference been deleted?
/*--------------------------------------------------------------------------------
* Constructors
@@ -170,6 +171,23 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
} // end constructor
/*--------------------------------------------------------------------------------
* finalize() function
*--------------------------------------------------------------------------------
*/
protected void finalize()
{
if (confdata!=null)
confdata.rd_release();
confdata = null;
engine = null;
sig = null;
datapool = null;
cache = null;
} // end finalize
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
@@ -179,6 +197,8 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
{
if (confdata==null)
{ // attempt to load the ConferenceSIGContext
if (deleted)
throw new DataException("This conference has been deleted.");
confdata = engine.getConferenceDataObject(confid);
// clear cache when we get the real confdata
@@ -194,6 +214,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
{
if (confdata==null)
{ // we need to load the ConferenceSIGContext...
if (deleted)
return null; // no return on deletion
try
{ // attempt to load the ConferenceSIGContext
confdata = engine.getConferenceDataObject(confid);
@@ -442,6 +465,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public synchronized void setSIGGrantedLevel(SIGBackend sig, int new_level) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -501,6 +527,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public synchronized void setSequence(short seq) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
try
@@ -543,6 +572,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public void setHideList(SIGBackend sig, boolean flag) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
@@ -697,4 +729,86 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
} // end getTopTopic
public List getMemberList() throws DataException
{
return getConferenceData().getMemberList();
} // end getMemberList
public int getMemberLevel(int uid) throws DataException
{
return getConferenceData().getMemberLevel(uid);
} // end getMemberLevel
public boolean canDeleteConference(int level)
{
ConferenceData c = getConferenceDataNE();
if (c==null)
return false;
if (level<this.level)
return c.canDeleteConference(this.level);
else
return c.canDeleteConference(level);
} // end canDeleteConference
public void delete(SIGBackend sig) throws DataException
{
ConferenceData c = getConferenceData();
Connection conn = null;
boolean delete_core = true;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// see if we have to delete the core object as well
StringBuffer sql = new StringBuffer("SELECT sigid FROM sigtoconf WHERE confid = ");
sql.append(confid).append(" AND sigid <> ").append(this.sig.realSIGID()).append(" LIMIT 1;");
ResultSet rs = stmt.executeQuery(sql.toString());
if (rs.next())
delete_core = false; // we don't delete the core yet
// remove the row that links this conference to this SIG
sql.setLength(0);
sql.append("DELETE FROM sigtoconf WHERE confid = ").append(confid).append(" AND sigid = ");
sql.append(this.sig.realSIGID()).append(';');
stmt.executeUpdate(sql.toString());
// record that we've been deleted
level = 0;
sequence = -1;
hide_list = true;
cache = null;
deleted = true;
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error deleting conference entry: " + e.getMessage(),e);
throw new DataException("unable to delete conference information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
if (delete_core)
{ // the conference is not linked to any other SIGs - we need to delete the core as well
c.delete(sig);
engine.detachConferenceDataObject(confid);
} // end if
// detach our own reference from the lower-level object
confdata = null;
c.rd_release();
} // end delete
} // end class ConferenceSIGContextImpl

View File

@@ -139,6 +139,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
private String pseud; // default pseud to use in this conference
private java.util.Date last_read; // last date we read this conference
private java.util.Date last_post; // last date we posted to this conference
private boolean deleted = false; // has conference been deleted?
/*--------------------------------------------------------------------------------
* Constructors
@@ -202,6 +203,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{
if (confdata==null)
{ // attempt to load the ConferenceSIGContext
if (deleted)
throw new DataException("This conference has been deleted.");
confdata = sig.getConferenceDataObject(confid);
// clear cache when we get the real confdata
@@ -217,6 +220,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{
if (confdata==null)
{ // we need to load the ConferenceSIGContext...
if (deleted)
return null; // no return on deletion
try
{ // attempt to load the ConferenceSIGContext
confdata = sig.getConferenceDataObject(confid);
@@ -262,6 +268,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
private void tryLoadSettings(Connection conn) throws DataException
{
if (deleted)
return; // this is a no-op
try
{ // look up the conference settings for this user
Statement stmt = conn.createStatement();
@@ -609,7 +618,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end removeAlias
public void addMember(int uid, boolean as_host) throws DataException, AccessError
public void setMembership(int uid, int grant_level) throws DataException, AccessError
{
if (!(getConferenceData().canChangeConference(level)))
{ // this user can't modify the conference security
@@ -618,13 +627,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
// figure out which level to grant the user
int grant_level;
if (as_host)
grant_level = DefaultLevels.hostConference();
else
grant_level = DefaultLevels.memberConference();
// call down to set the level
getConferenceData().setMembership(sig,uid,grant_level);
@@ -632,28 +634,23 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
if (uid==sig.realUID())
recalcLevel(grant_level);
} // end setMembership
public void addMember(int uid, boolean as_host) throws DataException, AccessError
{
setMembership(uid,(as_host ? DefaultLevels.hostConference() : DefaultLevels.memberConference()));
} // end addMember
public void removeMember(int uid) throws DataException, AccessError
{
if (!(getConferenceData().canChangeConference(level)))
{ // this user can't modify the conference security
logger.error("user not permitted to change membership");
throw new AccessError("You are not permitted to change the membership of this conference.");
} // end if
// call down to set the level
getConferenceData().setMembership(sig,uid,-1);
// If we adjusted our OWN level, reflect that change.
if (uid==sig.realUID())
recalcLevel(-1);
setMembership(uid,-1);
} // end removeMember
public int getSIGGrantedLevel() throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to retrieve security info");
@@ -661,12 +658,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
return getConferenceData().getSIGGrantedLevel();
return c.getSIGGrantedLevel();
} // end getSIGGrantedLevel
public void setSIGGrantedLevel(int new_level) throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to change security info");
@@ -674,12 +672,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
getConferenceData().setSIGGrantedLevel(sig,new_level);
c.setSIGGrantedLevel(sig,new_level);
} // end setSIGGrantedLevel
public short getSequence() throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to retrieve layout info");
@@ -687,12 +686,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
return getConferenceData().getSequence();
return c.getSequence();
} // end getSequence
public void setSequence(short seq) throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to set layout info");
@@ -700,12 +700,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
getConferenceData().setSequence(seq);
c.setSequence(seq);
} // end setSequence
public boolean getHideList() throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to retrieve security info");
@@ -713,12 +714,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
return getConferenceData().getHideList();
return c.getHideList();
} // end getHideList
public void setHideList(boolean flag) throws DataException, AccessError
{
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security
logger.error("user not permitted to change security info");
@@ -726,7 +728,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if
getConferenceData().setHideList(sig,flag);
c.setHideList(sig,flag);
} // end setHideList
@@ -740,6 +742,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{
if (sig.userIsAnonymous())
return; // anonymous user can't change pseud
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // pooled database connection
@@ -787,6 +791,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public boolean anyUnread()
{
if (deleted)
return false;
Connection conn = null; // pooled database connection
try
@@ -832,7 +838,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to change membership");
logger.error("user not permitted to get topics");
throw new AccessError("You are not permitted to read this conference.");
} // end if
@@ -929,7 +935,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to change membership");
logger.error("user not permitted to get messages");
throw new AccessError("You are not permitted to read this conference.");
} // end if
@@ -953,8 +959,15 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getNewTopicPreviewChecker
public void fixSeen() throws DataException
public void fixSeen() throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to set unread messages");
throw new AccessError("You are not permitted to read this conference.");
} // end if
if (sig.userIsAnonymous())
return; // anonymous user can't fixseen
@@ -1018,8 +1031,15 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end fixSeen
public List getActivePosters(int skip, int limit) throws DataException
public List getActivePosters(int skip, int limit) throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get posters list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
Connection conn = null;
Vector rc = new Vector();
@@ -1066,20 +1086,27 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getActivePosters
public List getActivePosters(int limit) throws DataException
public List getActivePosters(int limit) throws DataException, AccessError
{
return getActivePosters(0,limit);
} // end getActivePosters
public List getActivePosters() throws DataException
public List getActivePosters() throws DataException, AccessError
{
return getActivePosters(-1,-1);
} // end getActivePosters
public List getActiveReaders(int skip, int limit) throws DataException
public List getActiveReaders(int skip, int limit) throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get readers list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
Connection conn = null;
Vector rc = new Vector();
@@ -1126,18 +1153,81 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getActiveReaders
public List getActiveReaders(int limit) throws DataException
public List getActiveReaders(int limit) throws DataException, AccessError
{
return getActiveReaders(0,limit);
} // end getActiveReaders
public List getActiveReaders() throws DataException
public List getActiveReaders() throws DataException, AccessError
{
return getActiveReaders(-1,-1);
} // end getActiveReaders
public List getMemberList() throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get member list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
return getConferenceData().getMemberList();
} // end getMemberList
public int getMemberLevel(int uid) throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get member data");
throw new AccessError("You are not permitted to read this conference.");
} // end if
return getConferenceData().getMemberLevel(uid);
} // end getMemberLevel
public void delete() throws DataException, AccessError
{
ConferenceSIGContext ctxt = getConferenceData();
if (!(ctxt.canDeleteConference(level)) || !(sig.userCanDeleteSubobjects()))
{ // no way can we delete this conference, not NO way!
logger.error("user not permitted to delete conference");
throw new AccessError("You are not permitted to delete this conference.");
} // end if
// call the methods required to delete the conference
ctxt.delete(sig);
sig.detachConferenceDataObject(confid);
// flag that we've been deleted
cache = null;
settings_loaded = true;
pseud = null;
last_read = null;
last_post = null;
deleted = true;
// detach our references from the lower-level object
confdata = null;
ctxt.rd_release();
} // end delete
public boolean canDeleteConference()
{
ConferenceSIGContext c = getConferenceDataNE();
if (c==null)
return false;
return (c.canDeleteConference(level) && sig.userCanDeleteSubobjects());
} // end canDeleteConference
/*--------------------------------------------------------------------------------
* Implementations from interface UserBackend
*--------------------------------------------------------------------------------
@@ -1214,6 +1304,18 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end realSIGAlias
public void detachConferenceDataObject(int confid) throws DataException
{
sig.detachConferenceDataObject(confid);
} // end detachConferenceDataObject
public boolean userCanDeleteSubobjects()
{
return sig.userCanDeleteSubobjects();
} // end userCanDeleteSubobjects
/*--------------------------------------------------------------------------------
* Implementations from interface ConferenceBackend
*--------------------------------------------------------------------------------
@@ -1236,7 +1338,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public void touchRead(Connection conn) throws SQLException
{
if (sig.userIsAnonymous())
if (deleted || sig.userIsAnonymous())
return; // anonymous user can't update squat
Statement stmt = conn.createStatement();
@@ -1268,7 +1370,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public void touchPost(Connection conn, java.util.Date post_date) throws SQLException
{
if (sig.userIsAnonymous())
if (deleted || sig.userIsAnonymous())
return; // anonymous user can't update squat
Statement stmt = conn.createStatement();
@@ -1299,6 +1401,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public String realConfAlias()
{
if (deleted)
return null;
try
{ // just pull it from the lower-level object
return getConferenceData().getAnAlias();

View File

@@ -7,7 +7,7 @@
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
@@ -32,6 +32,9 @@ public interface EngineBackend
public static final int IP_POSTSPERPAGE = 0;
public static final int IP_POSTSATTOP = 1;
public static final int IP_MAXSEARCHRETURN = 2;
public static final int IP_MAXSIGMEMBERDISPLAY = 3;
public static final int IP_MAXCONFMEMBERDISPLAY = 4;
public abstract SimpleEmailer createEmailer();
@@ -45,6 +48,8 @@ public interface EngineBackend
public abstract SIGData getSIGDataObject(int sigid) throws DataException;
public abstract void detachSIGDataObject(int sigid);
public abstract BitSet getLockedFeaturesMask();
public abstract List getSIGFeatureSet(BitSet enabled_features, int level, boolean read_privs);
@@ -63,6 +68,8 @@ public interface EngineBackend
public abstract ConferenceData getConferenceDataObject(int confid) throws DataException;
public abstract void detachConferenceDataObject(int confid);
public abstract void saveAuditRecord(AuditRecord ar);
public abstract void registerNewConference(ConferenceData conf);

View File

@@ -33,4 +33,8 @@ public interface SIGBackend extends UserBackend
public abstract String realSIGAlias();
public abstract void detachConferenceDataObject(int confid) throws DataException;
public abstract boolean userCanDeleteSubobjects();
} // end interface SIGBackend

View File

@@ -78,7 +78,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
SIGCoreData(EngineBackend engine, DataPool datapool, int sigid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("new SIGCoreData for SIG " + String.valueOf(sigid));
logger.debug("new SIGCoreData for SIG " + sigid);
this.engine = engine;
this.datapool = datapool;
this.sigid = sigid;
@@ -95,7 +95,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
sql.append(sigid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new DataException("SIG #" + String.valueOf(sigid) + " does not exist in the database.");
throw new DataException("SIG #" + sigid + " does not exist in the database.");
loadData(rs); // load the SIG data
@@ -129,7 +129,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
BitSet features)
{
if (logger.isDebugEnabled())
logger.debug("new SIGCoreData for BRAND NEW SIG " + String.valueOf(sigid));
logger.debug("new SIGCoreData for BRAND NEW SIG " + sigid);
this.engine = engine;
this.datapool = datapool;
this.sigid = sigid;
@@ -218,8 +218,8 @@ class SIGCoreData implements SIGData, SIGDataBackend
alias = rs.getString("alias");
if (logger.isDebugEnabled())
logger.debug("Loaded data for SIG \"" + name + "\" (ID " + String.valueOf(sigid) + ", alias '"
+ alias + "') successfully");
logger.debug("Loaded data for SIG \"" + name + "\" (ID " + sigid + ", alias '" + alias
+ "') successfully");
} // end loadData
@@ -438,13 +438,13 @@ class SIGCoreData implements SIGData, SIGDataBackend
{ // contact being established for the first time
contactid = ci.getContactID();
if (logger.isDebugEnabled())
logger.debug("established new contact ID (" + String.valueOf(contactid) + ") for this SIG");
logger.debug("established new contact ID (" + contactid + ") for this SIG");
} // end if
touchUpdate(conn);
ar = new AuditRecord(AuditRecord.SIG_CONTACT_INFO,user.realUID(),user.userRemoteAddress(),sigid,
"contactid=" + String.valueOf(contactid));
"contactid=" + contactid);
} // end try
catch (ClassCastException cce)
@@ -691,7 +691,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
this.category_id = catid;
last_update = now;
ar = new AuditRecord(AuditRecord.SIG_CATEGORY,user.realUID(),user.userRemoteAddress(),sigid,
"catid=" + String.valueOf(catid));
"catid=" + catid);
} // end try
catch (SQLException e)
@@ -879,7 +879,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
hidden_search = search;
last_update = now;
ar = new AuditRecord(AuditRecord.SIG_HIDE_INFO,user.realUID(),user.userRemoteAddress(),sigid,
"dir=" + String.valueOf(directory) + ",search=" + String.valueOf(search));
"dir=" + directory + ",search=" + search);
} // end try
catch (SQLException e)
@@ -932,7 +932,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
members_only = flag;
last_update = now;
ar = new AuditRecord(AuditRecord.SIG_MEMBERS_ONLY,user.realUID(),user.userRemoteAddress(),sigid,
"flag=" + String.valueOf(flag));
"flag=" + flag);
} // end try
catch (SQLException e)
@@ -1013,7 +1013,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
{ // can't find the join key?
logger.error("SIG " + String.valueOf(sigid) + "appears to not be there");
logger.error("SIG " + sigid + "appears to not be there");
throw new DataException("Unable to find join key for SIG");
} // end if
@@ -1241,7 +1241,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
{ // update the SIG data and generate an audit record
touchUpdate(conn);
ar = new AuditRecord(AuditRecord.SET_MEMBERSHIP,user.realUID(),user.userRemoteAddress(),sigid,
"uid=" + String.valueOf(uid),"level=" + String.valueOf(grant_level));
"uid=" + uid,"level=" + grant_level);
} // end if
} // end try
@@ -1319,10 +1319,10 @@ class SIGCoreData implements SIGData, SIGDataBackend
} // end isFeaturePresent
public ConferenceSIGContext getConferenceDataObject(int confid) throws DataException
public synchronized ConferenceSIGContext getConferenceDataObject(int confid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("getConferenceDataObject(" + String.valueOf(confid) + ")...");
logger.debug("getConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceSIGContext csc = (ConferenceSIGContext)(conf_objects.get(the_confid));
@@ -1346,6 +1346,24 @@ class SIGCoreData implements SIGData, SIGDataBackend
} // end getConferenceDataObject
public synchronized void detachConferenceDataObject(int confid)
{
if (logger.isDebugEnabled())
logger.debug("detachConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceSIGContext csc = (ConferenceSIGContext)(conf_objects.get(the_confid));
if (csc!=null)
{ // remove from the hashtable
conf_objects.remove(the_confid);
csc.rd_release();
if (logger.isDebugEnabled())
logger.debug("...reference released");
} // end if
} // end detachConferenceDataObject
public ConferenceSIGContext createConference(SIGBackend sig, String name, String alias, String description,
boolean pvt, boolean hide_list) throws DataException
{
@@ -1362,19 +1380,271 @@ class SIGCoreData implements SIGData, SIGDataBackend
cdata.rd_release();
rcs = null;
// Register this object with our local cache of ConferenceSIGData objects.
Integer the_confid = new Integer(conf.getConfID());
if (conf_objects.get(the_confid)!=null)
throw new InternalStateError("ConfID " + the_confid.toString() + " already exists...but it CAN'T HAVE!");
synchronized (this)
{ // Register this object with our local cache of ConferenceSIGData objects.
Integer the_confid = new Integer(conf.getConfID());
if (conf_objects.get(the_confid)!=null)
throw new InternalStateError("ConfID " + the_confid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache
conf.rd_addRef();
conf_objects.put(the_confid,conf);
// throw an extra reference on it and dump it in the object cache
conf.rd_addRef();
conf_objects.put(the_confid,conf);
} // end synchronized block
return conf; // pass it up to the next level
} // end createConference
public List searchForMembers(int field, int mode, String term, int offset, int count,
boolean include_hidden) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("Member search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
+ term + "', offset = " + offset + ", count = " + count);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid).append(" AND ");
switch (field)
{ // determine which field to search on
case SearchMode.FIELD_USER_NAME:
sql.append("u.username ");
break;
case SearchMode.FIELD_USER_DESCRIPTION:
sql.append("u.description ");
break;
case SearchMode.FIELD_USER_GIVEN_NAME:
sql.append("c.given_name ");
break;
case SearchMode.FIELD_USER_FAMILY_NAME:
sql.append("c.family_name ");
break;
default:
throw new DataException("invalid search field specified");
} // end switch
switch (mode)
{ // compose SQL in different ways depending on the search term
case SearchMode.SEARCH_PREFIX:
sql.append("LIKE '").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_SUBSTRING:
sql.append("LIKE '%").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_REGEXP:
sql.append("REGEXP '").append(SQLUtil.encodeString(term)).append('\'');
break;
default:
throw new DataException("invalid search mode specified");
} // end switch
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0 ORDER BY u.username LIMIT ").append(offset).append(", ");
sql.append(count+1).append(';');
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end searchForMembers
public int getSearchMemberCount(int field, int mode, String term, boolean include_hidden)
throws DataException
{
if (logger.isDebugEnabled())
logger.debug("User search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
+ term + "'");
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid).append(" AND ");
switch (field)
{ // determine which field to search on
case SearchMode.FIELD_USER_NAME:
sql.append("u.username ");
break;
case SearchMode.FIELD_USER_DESCRIPTION:
sql.append("u.description ");
break;
case SearchMode.FIELD_USER_GIVEN_NAME:
sql.append("c.given_name ");
break;
case SearchMode.FIELD_USER_FAMILY_NAME:
sql.append("c.family_name ");
break;
default:
throw new DataException("invalid search field specified");
} // end switch
switch (mode)
{ // compose SQL in different ways depending on the search term
case SearchMode.SEARCH_PREFIX:
sql.append("LIKE '").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_SUBSTRING:
sql.append("LIKE '%").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_REGEXP:
sql.append("REGEXP '").append(SQLUtil.encodeString(term)).append('\'');
break;
default:
throw new DataException("invalid search mode specified");
} // end switch
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("getSearchMemberCount failure (MUST have 1 row!)");
return rs.getInt(1);
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end getSearchMemberCount
public List getMemberList(boolean include_hidden) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("Member list: SIG = " + sigid);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid);
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0 ORDER BY u.username;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end getMemberList
/*--------------------------------------------------------------------------------
* Implementations from interface SIGDataBackend
*--------------------------------------------------------------------------------

View File

@@ -132,8 +132,18 @@ public interface SIGData extends ReferencedData
public abstract ConferenceSIGContext getConferenceDataObject(int confid) throws DataException;
public abstract void detachConferenceDataObject(int confid);
public abstract ConferenceSIGContext createConference(SIGBackend sig, String name, String alias,
String description, boolean pvt, boolean hide_list)
throws DataException;
public abstract List searchForMembers(int field, int mode, String term, int offset, int count,
boolean include_hidden) throws DataException;
public abstract int getSearchMemberCount(int field, int mode, String term, boolean include_hidden)
throws DataException;
public abstract List getMemberList(boolean include_hidden) throws DataException;
} // end interface SIGData

View File

@@ -1073,6 +1073,25 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end canCreateConference
public List searchForMembers(int field, int mode, String term, int offset, int count)
throws DataException
{
return getSIGData().searchForMembers(field,mode,term,offset,count,Capability.showHiddenSIGMembers(level));
} // end searchForMembers
public int getSearchMemberCount(int field, int mode, String term) throws DataException
{
return getSIGData().getSearchMemberCount(field,mode,term,Capability.showHiddenSIGMembers(level));
} // end getSearchMemberCount
public List getMemberList() throws DataException
{
return getSIGData().getMemberList(Capability.showHiddenSIGMembers(level));
} // end getMemberList
/*--------------------------------------------------------------------------------
* Implementations from interface UserBackend
*--------------------------------------------------------------------------------
@@ -1155,6 +1174,18 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end realSIGAlias
public void detachConferenceDataObject(int confid) throws DataException
{
getSIGData().detachConferenceDataObject(confid);
} // end detachConferenceDataObject
public boolean userCanDeleteSubobjects()
{
return userCanCreateSubobjects();
} // end userCanDeleteSubobjects
/*--------------------------------------------------------------------------------
* Static operations for use within the implementation package
*--------------------------------------------------------------------------------

View File

@@ -129,4 +129,11 @@ class UserFoundImpl implements UserFound
} // end getLevel
public UserFound createNewLevel(int level)
{
return new UserFoundImpl(this.uid,this.name,this.description,this.given_name,this.family_name,
this.locality,this.region,this.country,level);
} // end createNewLevel
} // end class UserFoundImpl

View File

@@ -242,7 +242,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
private void loadDefaults(Statement stmt) throws SQLException, DataException
{
final String query = "SELECT posts_per_page, old_posts_at_top FROM globals;";
final String query =
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page "
+ "FROM globals;";
ResultSet rs = stmt.executeQuery(query);
if (!(rs.next()))
throw new DataException("Globals table does not appear to be loaded!");
@@ -250,6 +252,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
// stash the globals from the database
gp_ints[IP_POSTSPERPAGE] = rs.getInt(1);
gp_ints[IP_POSTSATTOP] = rs.getInt(2);
gp_ints[IP_MAXSEARCHRETURN] = rs.getInt(3);
gp_ints[IP_MAXSIGMEMBERDISPLAY] = rs.getInt(4);
gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5);
} // end loadDefaults
@@ -381,7 +386,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end for
if (logger.isDebugEnabled())
logger.debug(String.valueOf(stock_messages.size()) + " stock messages loaded from config");
logger.debug(stock_messages.size() + " stock messages loaded from config");
} // end try
catch (ConfigException ce)
@@ -393,7 +398,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end catch
// Allocate the global parameter arrays.
gp_ints = new int[2];
gp_ints = new int[5];
// initialize anything that requires us to pull from the database
Connection conn = null;
@@ -419,7 +424,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
features = new VeniceFeatureDef[++max_value];
System.arraycopy(tmp_array,0,features,0,max_value);
if (logger.isDebugEnabled())
logger.debug(String.valueOf(max_value) + " features loaded from database");
logger.debug(max_value + " features loaded from database");
// load the global defaults
loadDefaults(stmt);
@@ -556,13 +561,13 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next())
{ // load up a stack of memory objects with the country list
Country c = new CountryImpl(rs.getString("code"),rs.getString("name"));
Country c = new CountryImpl(rs.getString(1),rs.getString(2));
rc.add(c);
} // end while
if (logger.isDebugEnabled())
logger.debug("getCountryList(): loaded " + String.valueOf(rc.size()) + " country names");
logger.debug("getCountryList(): loaded " + rc.size() + " country names");
} // end try
catch (SQLException e)
@@ -596,13 +601,13 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next())
{ // load up a stack of memory objects with the country list
Language l = new LanguageImpl(rs.getString("code"),rs.getString("name"));
Language l = new LanguageImpl(rs.getString(1),rs.getString(2));
rc.add(l);
} // end while
if (logger.isDebugEnabled())
logger.debug("getLanguageList(): loaded " + String.valueOf(rc.size()) + " language names");
logger.debug("getLanguageList(): loaded " + rc.size() + " language names");
} // end try
catch (SQLException e)
@@ -649,9 +654,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // look for a user name matching this user record
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT c.email AS email FROM users u, contacts c "
+ "WHERE u.contactid = c.contactid AND u.username = '"
+ SQLUtil.encodeString(username) + "';");
ResultSet rs = stmt.executeQuery("SELECT c.email FROM users u, contacts c WHERE u.contactid = "
+ "c.contactid AND u.username = '" + SQLUtil.encodeString(username)
+ "';");
if (!(rs.next()))
{ // could not find email address
logger.warn("getEmailAddressForUser(\"" + username + "\") => not found!");
@@ -660,7 +665,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if
String rc = rs.getString("email");
String rc = rs.getString(1);
if (logger.isDebugEnabled())
logger.debug("getEmailAddressForUser(\"" + username + "\") => \"" + rc + "\"");
return rc;
@@ -690,9 +695,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // look for a user name matching this user record
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT c.email AS email, u.passreminder AS passreminder "
+ "FROM users u, contacts c WHERE u.contactid = c.contactid "
+ "AND u.username = '");
StringBuffer sql = new StringBuffer("SELECT c.email, u.passreminder FROM users u, contacts c WHERE "
+ "u.contactid = c.contactid AND u.username = '");
sql.append(SQLUtil.encodeString(username)).append("';");
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
@@ -703,7 +707,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if
String email_addr = rs.getString("email");
String email_addr = rs.getString(1);
if (logger.isDebugEnabled())
logger.debug("sendPasswordReminder(\"" + username + "\") going out to \"" + email_addr + "\"");
@@ -717,7 +721,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if
message = StringUtil.replaceAllInstances(message,"$USERNAME",username);
message = StringUtil.replaceAllInstances(message,"$REMINDER",rs.getString("passreminder"));
message = StringUtil.replaceAllInstances(message,"$REMINDER",rs.getString(2));
// Create the emailer and send the message.
SimpleEmailer emailer = createEmailer();
@@ -796,7 +800,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
new_uid = rs.getInt(1);
if (logger.isDebugEnabled())
logger.debug("...created user \"" + username + "\" with UID " + String.valueOf(new_uid));
logger.debug("...created user \"" + username + "\" with UID " + new_uid);
// add a UserPrefs record for this user, too
sql.setLength(0);
@@ -974,9 +978,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public List searchForUsers(int field, int mode, String term, int offset, int count) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("User search: field = " + String.valueOf(field) + ", mode = " + String.valueOf(mode)
+ ", term '" + term + "', offset = " + String.valueOf(offset) + ", count = "
+ String.valueOf(count));
logger.debug("User search: field = " + field + ", mode = " + mode + ", term '" + term + "', offset = "
+ offset + ", count = " + count);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
@@ -985,11 +988,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT u.uid AS uid, u.username AS username, u.description "
+ "AS description, c.given_name AS given_name, c.family_name AS "
+ "family_name, c.locality AS locality, c.region AS region, "
+ "c.country AS country FROM users u, contacts c WHERE "
+ "u.contactid = c.contactid AND ");
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country FROM users u, "
+ "contacts c WHERE u.contactid = c.contactid AND ");
switch (field)
{ // determine which field to search on
@@ -1044,10 +1045,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt("uid"),rs.getString("username"),
rs.getString("description"),rs.getString("given_name"),
rs.getString("family_name"),rs.getString("locality"),
rs.getString("region"),rs.getString("country"));
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
@@ -1074,8 +1073,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public int getSearchUserCount(int field, int mode, String term) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("User search: field = " + String.valueOf(field) + ", mode = " + String.valueOf(mode)
+ ", term '" + term + "'");
logger.debug("User search: field = " + field + ", mode = " + mode + ", term '" + term + "'");
Connection conn = null; // pooled database connection
@@ -1083,8 +1081,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT COUNT(*) AS total FROM users u, contacts c WHERE "
+ "u.contactid = c.contactid AND ");
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM users u, contacts c WHERE u.contactid = "
+ "c.contactid AND ");
switch (field)
{ // determine which field to search on
@@ -1140,7 +1138,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
if (!(rs.next()))
throw new InternalStateError("getSearchUserCount search failure (MUST have 1 row!)");
return rs.getInt("total");
return rs.getInt(1);
} // end try
catch (SQLException e)
@@ -1160,7 +1158,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public int getStdNumSearchResults()
{
return 20; // TODO: make this a config file option
return gp_ints[IP_MAXSEARCHRETURN];
} // end getStdNumSearchResults
@@ -1245,6 +1243,18 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getNumOldPostsBeforeNew
public int getMaxNumConferenceMembersDisplay()
{
return gp_ints[IP_MAXCONFMEMBERDISPLAY];
} // end getMaxNumConferenceMembersDisplay
public int getMaxNumSIGMembersDisplay()
{
return gp_ints[IP_MAXSIGMEMBERDISPLAY];
} // end getMaxNumSIGMembersDisplay
/*--------------------------------------------------------------------------------
* Implementations from interface EngineBackend
*--------------------------------------------------------------------------------
@@ -1357,11 +1367,11 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getLanguageNameForCode
public SIGData getSIGDataObject(int sigid) throws DataException
public synchronized SIGData getSIGDataObject(int sigid) throws DataException
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("getSIGDataObject(" + String.valueOf(sigid) + ")...");
logger.debug("getSIGDataObject(" + sigid + ")...");
Integer the_sigid = new Integer(sigid);
SIGData sd = (SIGData)(sig_objects.get(the_sigid));
@@ -1385,6 +1395,25 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getSIGDataObject
public synchronized void detachSIGDataObject(int sigid)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("detachSIGDataObject(" + sigid + ")...");
Integer the_sigid = new Integer(sigid);
SIGData sd = (SIGData)(sig_objects.get(the_sigid));
if (sd!=null)
{ // pull the reference out of our hashtable
sig_objects.remove(the_sigid);
sd.rd_release();
if (logger.isDebugEnabled())
logger.debug("...reference detached");
} // end if
} // end detachSIGDataObject
public BitSet getLockedFeaturesMask()
{
checkInitialized();
@@ -1420,7 +1449,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if and for
if (logger.isDebugEnabled())
logger.debug("getSIGFeatureSet() loaded " + String.valueOf(rc.size()) + " elements");
logger.debug("getSIGFeatureSet() loaded " + rc.size() + " elements");
return new ReadOnlyVector(rc); // wrap the vector for return
@@ -1431,14 +1460,14 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
checkInitialized();
if ((code<0) || (code>=features.length))
{ // the index is out of bounds!
logger.error("getAppletForFeature(" + String.valueOf(code) + ") => out of range");
logger.error("getAppletForFeature(" + code + ") => out of range");
throw new IndexOutOfBoundsException("invalid feature code");
} // end if
String rc = features[code].getApplet();
if (logger.isDebugEnabled())
logger.debug("getAppletForFeature(" + String.valueOf(code) + ") => \"" + rc + "\"");
logger.debug("getAppletForFeature(" + code + ") => \"" + rc + "\"");
return rc;
} // end getAppletForFeature
@@ -1463,15 +1492,15 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getDefaultFeaturesMask
public void registerNewSIG(SIGData sig)
public synchronized void registerNewSIG(SIGData sig)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("registerNewSIG(" + String.valueOf(sig.getID()) + ")...");
logger.debug("registerNewSIG(" + sig.getID() + ")...");
Integer the_sigid = new Integer(sig.getID());
if (sig_objects.get(the_sigid)!=null)
throw new InternalStateError("SIGID " + the_sigid.toString() + " already exists...but it CAN'T HAVE!");
throw new InternalStateError("SIGID " + the_sigid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache
sig.rd_addRef();
@@ -1501,11 +1530,11 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end canAccessFeature
public ConferenceData getConferenceDataObject(int confid) throws DataException
public synchronized ConferenceData getConferenceDataObject(int confid) throws DataException
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("getConferenceDataObject(" + String.valueOf(confid) + ")...");
logger.debug("getConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceData cd = (ConferenceData)(conf_objects.get(the_confid));
@@ -1529,6 +1558,25 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getConferenceDataObject
public synchronized void detachConferenceDataObject(int confid)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("detachConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceData cd = (ConferenceData)(conf_objects.get(the_confid));
if (cd!=null)
{ // remove it from our hashtable
conf_objects.remove(the_confid);
cd.rd_release();
if (logger.isDebugEnabled())
logger.debug("...detached reference");
} // end if
} // end detachConferenceDataObject
public void saveAuditRecord(AuditRecord ar)
{
checkInitialized();
@@ -1557,15 +1605,15 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end saveAuditRecord
public void registerNewConference(ConferenceData conf)
public synchronized void registerNewConference(ConferenceData conf)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("registerNewConference(" + String.valueOf(conf.getID()) + ")...");
logger.debug("registerNewConference(" + conf.getID() + ")...");
Integer the_confid = new Integer(conf.getID());
if (conf_objects.get(the_confid)!=null)
throw new InternalStateError("ConfID " + the_confid.toString() + " already exists...but it CAN'T HAVE!");
throw new InternalStateError("ConfID " + the_confid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache
conf.rd_addRef();

View File

@@ -59,5 +59,6 @@ public interface Audit
public static final int SCRIBBLE_MESSAGE = 312;
public static final int NUKE_MESSAGE = 313;
public static final int UPLOAD_ATTACHMENT = 314;
public static final int DELETE_CONF = 315;
} // end interface Audit

View File

@@ -63,6 +63,7 @@ public class Role implements Comparable, SecLevels
*--------------------------------------------------------------------------------
*/
private static Role not_in_list = null;
private static Role no_access = null;
private static Role unrestricted_user = null;
private static Vector global_low = null;
@@ -99,6 +100,9 @@ public class Role implements Comparable, SecLevels
private static void initAllSets()
{
if (not_in_list==null)
not_in_list = new Role(0,"(not in list)");
if (no_access==null)
no_access = new Role(NO_ACCESS,"No Access");
@@ -343,4 +347,18 @@ public class Role implements Comparable, SecLevels
} // end getConferenceDeleteList
public static List getConferenceMemberLevelChoices()
{
initAllSets();
Vector rc = new Vector();
rc.add(not_in_list);
rc.addAll(global_low);
rc.addAll(sig_low);
rc.addAll(conf_low);
rc.add(unrestricted_user);
rc.add(conf_high.lastElement());
return new ReadOnlyVector(rc);
} // end getConferenceMemberLevelChoices
} // end class Role

View File

@@ -18,6 +18,7 @@
package com.silverwrist.venice.servlets;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
@@ -33,6 +34,9 @@ public class ConfOperations extends VeniceServlet
*--------------------------------------------------------------------------------
*/
private static final String DELETE_CONFIRM_ATTR = "servlets.ConfOperations.delete.confirm";
private static final String DELETE_CONFIRM_PARAM = "confirm";
private static Category logger = Category.getInstance(ConfOperations.class.getName());
/*--------------------------------------------------------------------------------
@@ -174,6 +178,11 @@ public class ConfOperations extends VeniceServlet
conf.fixSeen();
} // end try
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // some sort of error in the database
return new ErrorBox("Database Error","Database error catching up conference: " + de.getMessage(),
@@ -282,9 +291,84 @@ public class ConfOperations extends VeniceServlet
on_error);
} // end catch
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
} // end if ("RP" and "RR" commands)
if (cmd.equals("M"))
{ // "M" - Manage Conference Membership (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=Q";
try
{ // display the conference member list!
ConferenceMembership m = new ConferenceMembership(engine,sig,conf);
m.doConferenceMemberList();
setMyLocation(request,"confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=M");
return m;
} // end try
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error listing conference members: " + de.getMessage(),
on_error);
} // end catch
catch (AccessError ae)
{ // some lack of access is causing problems
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
} // end if ("M" command)
if (cmd.equals("DEL"))
{ // "DEL" = "Delete Conference (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=Q";
if (!(conf.canDeleteConference()))
return new ErrorBox("Access Error","You do not have permission to delete this conference.",on_error);
if (ConfirmBox.isConfirmed(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM))
{ // we are confirmed - delete the conference!
try
{ // tell it to go away
conf.delete();
} // end try
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error deleting conference: " + de.getMessage(),
on_error);
} // end catch
catch (AccessError ae)
{ // some lack of access is causing problems
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
// that's it - trap back to the main conference list
throw new RedirectResult("confops?sig=" + sig.getSIGID());
} // end if
else
{ // generate a confirmation box and wait for confirmation
String message = "You are about to permanently delete the \"" + conf.getName() + "\" conference! "
+ "Are you sure you want to do this?";
return new ConfirmBox(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM,"Delete Conference",message,
"confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=DEL",
on_error);
} // end else
} // end if ("DEL" command)
// Any unrecognized command shows us the conference list.
on_error = "sigprofile?sig=" + sig.getSIGID();
try
@@ -572,6 +656,124 @@ public class ConfOperations extends VeniceServlet
} // end if ("A" command)
if (cmd.equals("M"))
{ // "M" - Manage Conference Membership (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=M";
if (isImageButtonClicked(request,"update"))
{ // the "update" command that changes all the security levels
HashMap org_vals = new HashMap();
HashMap new_vals = new HashMap();
try
{ // retrieve all parameters and filter them for the levels
Enumeration p_names = request.getParameterNames();
while (p_names.hasMoreElements())
{ // examine each parameter name in turn
String p_name = (String)(p_names.nextElement());
if (p_name.startsWith("zxcur_"))
{ // this is a current value (from a hidden field)
int uid = Integer.parseInt(p_name.substring(6));
int level = Integer.parseInt(request.getParameter(p_name));
org_vals.put(new Integer(uid),new Integer(level));
} // end if
else if (p_name.startsWith("zxnew_"))
{ // this is a new value (from a dropdown list box)
int uid = Integer.parseInt(p_name.substring(6));
int level = Integer.parseInt(request.getParameter(p_name));
new_vals.put(new Integer(uid),new Integer(level));
} // end else if
} // end while
if (org_vals.size()!=new_vals.size())
return new ErrorBox(null,"Invalid parameters.",on_error);
} // end try
catch (NumberFormatException nfe)
{ // error converting the parameters
return new ErrorBox(null,"Invalid parameter conversion.",on_error);
} // end catch
try
{ // loop through the hashmaps and set the value
Iterator it = org_vals.keySet().iterator();
while (it.hasNext())
{ // extract the UID, old level, and new level
Integer uid = (Integer)(it.next());
Integer org_level = (Integer)(org_vals.get(uid));
Integer new_level = (Integer)(new_vals.get(uid));
if (new_level==null) // whoops
return new ErrorBox(null,"Invalid new level parameter.",on_error);
int new_level_x = new_level.intValue();
if (new_level_x==0)
new_level_x = -1;
// call down to set the membership level
if (org_level.intValue()!=new_level_x)
conf.setMembership(uid.intValue(),new_level_x);
} // end while
} // end try
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // database error creating the conference
return new ErrorBox("Database Error","Database error setting memberships: " + de.getMessage(),
on_error);
} // end catch
// trap back to the conference membership display
throw new RedirectResult(on_error);
} // end if ("update" clicked)
if ( isImageButtonClicked(request,"search") || isImageButtonClicked(request,"previous")
|| isImageButtonClicked(request,"next"))
{ // create the new dialog box
ConferenceMembership m = new ConferenceMembership(engine,sig,conf);
try
{ // perform the search!
m.doSearch(request);
} // end try
catch (ValidationException ve)
{ // validation error - throw it back to the user
return new ErrorBox(null,ve.getMessage() + " Please try again.",on_error);
} // end catch
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // database error creating the conference
return new ErrorBox("Database Error","Database error updating conference: " + de.getMessage(),
on_error);
} // end catch
setMyLocation(request,on_error);
return m;
} // end if (search function clicked)
// we don't know what button was pressed
logger.error("no known button click on ConfOperations.doPost, cmd=M");
return new ErrorBox("Internal Error","Unknown command button pressed",on_error);
} // end if ("M" command)
// unrecognized command!
logger.error("invalid command to ConfOperations.doPost: " + cmd);
return new ErrorBox("Internal Error","Invalid command to ConfOperations.doPost",on_error);

View File

@@ -47,7 +47,8 @@ public class ConferenceActivity implements JSPRender
*--------------------------------------------------------------------------------
*/
public ConferenceActivity(SIGContext sig, ConferenceContext conf, boolean posters) throws DataException
public ConferenceActivity(SIGContext sig, ConferenceContext conf, boolean posters)
throws DataException, AccessError
{
this.sig = sig;
this.conf = conf;

View File

@@ -0,0 +1,337 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.servlets.format;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.ValidationException;
import com.silverwrist.venice.security.Role;
import com.silverwrist.venice.core.*;
public class ConferenceMembership implements JSPRender, SearchMode
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Attribute name for request attribute
protected static final String ATTR_NAME = "com.silverwrist.venice.content.ConferenceMembership";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private VeniceEngine engine; // reference to the engine
private SIGContext sig; // the SIG we're in
private ConferenceContext conf; // the conference being listed
private List display_list = null; // list of members to display
private boolean conf_members = false; // is this a list of conference members?
private int field = -1; // search field
private int mode = -1; // search mode
private String term = null; // search term
private int offset = 0; // search result offset
private int find_count = -1; // search results count
private List role_choices; // the list of security roles
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public ConferenceMembership(VeniceEngine engine, SIGContext sig, ConferenceContext conf)
{
this.engine = engine;
this.sig = sig;
this.conf = conf;
this.role_choices = Role.getConferenceMemberLevelChoices();
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private static int getParamInt(ServletRequest request, String name, int default_val)
{
String str = request.getParameter(name);
if (str==null)
return -1;
try
{ // parse the integer value
return Integer.parseInt(str);
} // end try
catch (NumberFormatException nfe)
{ // in case of conversion error, return default
return default_val;
} // end catch
} // end getParamInt
private static boolean isImageButtonClicked(ServletRequest request, String name)
{
String val = request.getParameter(name + ".x");
return (val!=null);
} // end isImageButtonClicked
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static ConferenceMembership retrieve(ServletRequest request)
{
return (ConferenceMembership)(request.getAttribute(ATTR_NAME));
} // end retrieve
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceContent
*--------------------------------------------------------------------------------
*/
public String getPageTitle(RenderData rdat)
{
return "Membership in Conference " + conf.getName();
} // end getPageTitle
/*--------------------------------------------------------------------------------
* Implementations from interface JSPRender
*--------------------------------------------------------------------------------
*/
public void store(ServletRequest request)
{
request.setAttribute(ATTR_NAME,this);
} // end store
public String getTargetJSPName()
{
return "conf_member.jsp";
} // end getTargetJSPName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void doConferenceMemberList() throws DataException, AccessError
{
this.display_list = conf.getMemberList();
this.conf_members = true;
this.term = "";
} // end doConferenceMemberList
public void doSearch(ServletRequest request) throws ValidationException, DataException, AccessError
{
// Validate the search field parameter.
field = getParamInt(request,"field",FIELD_USER_NAME);
if ( (field!=FIELD_USER_NAME) && (field!=FIELD_USER_DESCRIPTION) && (field!=FIELD_USER_GIVEN_NAME)
&& (field!=FIELD_USER_FAMILY_NAME))
throw new ValidationException("The field search parameter is not valid.");
// Validate the search mode parameter.
mode = getParamInt(request,"mode",SEARCH_PREFIX);
if ((mode!=SEARCH_PREFIX) && (mode!=SEARCH_SUBSTRING) && (mode!=SEARCH_REGEXP))
throw new ValidationException("The search mode parameter is not valid.");
// Retrieve the search term parameter.
term = request.getParameter("term");
if (term==null)
term = "";
// Retrieve the offset and find count parameters.
offset = getParamInt(request,"ofs",0);
find_count = getParamInt(request,"fcount",-1);
// Adjust the search return offset based on the command button click.
int count = getNumResultsDisplayed();
if (isImageButtonClicked(request,"search"))
offset = 0;
else if (isImageButtonClicked(request,"previous"))
{ // adjust the offset in the reverse direction
offset -= count;
if (offset<0)
offset = 0;
} // end else if
else if (isImageButtonClicked(request,"next"))
offset += count; // go forwards instead
else
throw new ValidationException("Unable to determine what action triggered the form.");
// Perform the search!
List intermediate = sig.searchForMembers(field,mode,term,offset,count);
if (find_count<0)
find_count = sig.getSearchMemberCount(field,mode,term);
// Create the real display list by getting the conference security levels.
Iterator it = intermediate.iterator();
Vector rc = new Vector(count+1);
while (it.hasNext())
{ // loop around and find the member level of every one
UserFound uf = (UserFound)(it.next());
int new_level = conf.getMemberLevel(uf.getUID());
if (new_level==-1)
new_level = 0;
rc.add(uf.createNewLevel(new_level));
} // end while
display_list = rc; // save display list for display
} // end doSearch
public int getSIGID()
{
return sig.getSIGID();
} // end getSIGID
public int getConfID()
{
return conf.getConfID();
} // end getConfID
public String getSIGName()
{
return sig.getName();
} // end getSIGName
public String getConfName()
{
return conf.getName();
} // end getConfName
public String getLocator()
{
return "sig=" + sig.getSIGID() + "&conf=" + conf.getConfID();
} // end getLocator
public boolean displayList()
{
if ((display_list==null) || (display_list.size()==0))
return false;
if (conf_members && (display_list.size()>engine.getMaxNumConferenceMembersDisplay()))
return false;
return true;
} // end displayList
public boolean conferenceMemberList()
{
return conf_members;
} // end conferenceMemberList
public int getSearchField()
{
return field;
} // end getSearchField
public int getSearchMode()
{
return mode;
} // end getSearchMode
public boolean searchFieldIs(int value)
{
return (field==value);
} // end searchFieldIs
public boolean searchModeIs(int value)
{
return (mode==value);
} // end searchModeIs
public String getSearchTerm()
{
return term;
} // end getSearchTerm
public int getFindCount()
{
return find_count;
} // end getFindCount
public int getOffset()
{
return offset;
} // end getOffset
public int getSize()
{
return display_list.size();
} // end getSize
public int getNumResultsDisplayed()
{
return engine.getStdNumSearchResults();
} // end getNumResultsDisplayed
public UserFound getItem(int ndx)
{
return (UserFound)(display_list.get(ndx));
} // end getItem
public void outputDropDown(Writer out, int uid, int cur_level) throws IOException
{
out.write("<INPUT TYPE=HIDDEN NAME=\"zxcur_" + uid + "\" VALUE=\"" + cur_level + "\">\n");
out.write("<SELECT NAME=\"zxnew_" + uid + "\" SIZE=1>\n");
Iterator it = role_choices.iterator();
while (it.hasNext())
{ // output the <OPTION> lines for the dropdown
Role r = (Role)(it.next());
out.write("<OPTION VALUE=\"" + r.getLevel() + "\"");
if (r.getLevel()==cur_level)
out.write(" SELECTED");
out.write(">" + r.getName() + "</OPTION>\n");
} // end while
out.write("</SELECT>\n");
} // end outputDropDown
} // end class ConferenceMembership

View File

@@ -66,7 +66,7 @@ public class ConfirmBox implements ContentRender
this.conf_num = rng.nextInt(0x1000000);
this.title = title;
this.message = message;
this.confirm_url = confirm_url + "&" + param_name + "=" + String.valueOf(this.conf_num);
this.confirm_url = confirm_url + "&" + param_name + "=" + this.conf_num;
this.deny_url = deny_url;
// Stash this object in the HTTP session.