added the initial implementation of the Universal Message Store (UniStore)

This commit is contained in:
Eric J. Bowersox 2003-06-10 20:33:45 +00:00
parent bbd46e4dc7
commit 7727dc61dd
21 changed files with 4025 additions and 4 deletions

View File

@ -94,6 +94,13 @@
</dictionary>
</object>
<object name="unistore" classname="com.silverwrist.dynamo.unistore.UniStoreManager" priority="5">
<database connection="data" namespaces="nscache"/>
<security object="srm"/>
<user-manager object="users"/>
<message-cache hardlimit="100" softlimit="1000"/>
</object>
<!-- Presentation and interface objects -->
<object name="remapper" classname="com.silverwrist.dynamo.servlet.RemapperData" priority="0">
<remap path="/verifyemail">

View File

@ -93,6 +93,13 @@
</dictionary>
</object>
<object name="unistore" classname="com.silverwrist.dynamo.unistore.UniStoreManager" priority="5">
<database connection="data" namespaces="nscache"/>
<security object="srm"/>
<user-manager object="users"/>
<message-cache hardlimit="100" softlimit="1000"/>
</object>
<!-- Presentation and interface objects -->
<object name="remapper" classname="com.silverwrist.dynamo.servlet.RemapperData" priority="0">
<remap path="/verifyemail">

View File

@ -274,7 +274,7 @@ CREATE TABLE us_text (
last_read DATETIME, # timestamp of when it was last read
data MEDIUMTEXT, # the text (16 Mb available)
PRIMARY KEY (msgid, part),
INDEX by_name (msgid, ident_nsid, ident_name)
UNIQUE INDEX by_name (msgid, ident_nsid, ident_name)
);
# UniStore: Text message part properties
@ -300,7 +300,7 @@ CREATE TABLE us_binary (
last_read DATETIME, # timestamp of when it was last read
data MEDIUMBLOB, # the actual data (16 Mb of space available)
PRIMARY KEY (msgid, part),
INDEX by_name (msgid, ident_nsid, ident_name)
UNIQUE INDEX by_name (msgid, ident_nsid, ident_name)
);
# UniStore: Binary message part properties

View File

@ -0,0 +1,148 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.util;
import java.io.*;
public class CacheInputStream extends FilterInputStream
{
/*---------------------------------------------------------------------------
* Static data members
*---------------------------------------------------------------------------
*/
private static final int MAX_MEMORY = 65536;
/*---------------------------------------------------------------------------
* Attributes
*---------------------------------------------------------------------------
*/
private File m_tempfile = null;
private int m_length = 0;
/*---------------------------------------------------------------------------
* Constructor
*---------------------------------------------------------------------------
*/
public CacheInputStream(String temp_prefix, InputStream data) throws IOException
{
super(new ByteArrayInputStream(new byte[0])); // dummy value
boolean complete = false;
OutputStream imstm = null;
try
{ // Copy data to a temporary stream.
ByteArrayOutputStream imstm_byte = new ByteArrayOutputStream();
imstm = imstm_byte;
byte[] buf = new byte[4096];
int rd = data.read(buf);
while (rd>=0)
{ // a simple copy loop, but with a twist
if (rd>0)
{ // if we go over memory limits, we'll have to create a tempfile
// and spill there...
if ((imstm_byte!=null) && ((rd + m_length)>MAX_MEMORY))
{ // get the source for the copy
ByteArrayInputStream copy_src =
new ByteArrayInputStream(imstm_byte.toByteArray());
// get the destination for the copy
m_tempfile = File.createTempFile(temp_prefix,null);
imstm = new FileOutputStream(m_tempfile);
// copy it and close the byte stream
IOUtils.copy(copy_src,imstm);
IOUtils.shutdown(copy_src);
IOUtils.shutdown(imstm_byte);
imstm_byte = null;
} // end if
// write data to the intermediate stream
imstm.write(buf,0,rd);
m_length += rd;
} // end if
rd = data.read(buf);
} // end while
if (imstm_byte!=null)
this.in = new ByteArrayInputStream(imstm_byte.toByteArray());
else
{ // close the file output stream, create a file input stream
IOUtils.shutdown(imstm);
imstm = null;
this.in = new FileInputStream(m_tempfile);
} // end else
complete = true;
} // end try
finally
{ // close down the intermediate stream
IOUtils.shutdown(imstm);
if (!complete && (m_tempfile!=null))
{ // delete the temporary file
m_tempfile.delete();
m_tempfile = null;
} // end if
} // end finally
} // end constructor
/*---------------------------------------------------------------------------
* Overrides from class FilterInputStream
*---------------------------------------------------------------------------
*/
public void close() throws IOException
{
try
{ // call through and close the stream
super.close();
} // end try
finally
{ // delete the temp file as well
if (m_tempfile!=null)
m_tempfile.delete();
m_tempfile = null;
} // end finally
} // end close
/*---------------------------------------------------------------------------
* External operations
*---------------------------------------------------------------------------
*/
int getLength()
{
return m_length;
} // end getLength
} // end class CacheInputStream

View File

@ -86,4 +86,10 @@ public interface Namespaces
public static final String SPELLCHECKER_PROPERTIES_NAMESPACE =
"http://www.silverwrist.com/NS/dynamo/2003/06/07/spellchecker.properties";
/**
* Namespace for the permissions for the Universal Message Store (UniStore).
*/
public static final String UNISTORE_PERMISSIONS_NAMESPACE =
"http://www.silverwrist.com/NS/dynamo/2003/06/10/unistore.permissions";
} // end interface Namespaces

View File

@ -3,6 +3,7 @@ advogato
ain't
anime
anla'shok
avaltus
bajor
bios
boitano
@ -22,6 +23,7 @@ cst
deflector
deflectors
delenn
denise
didn't
dilithium
docking
@ -39,10 +41,12 @@ faux
fett
followup
franklin
fsck
fucking
gamey
hairstyle
hairstyles
harasser
hasn't
haven't
he'd
@ -52,6 +56,7 @@ i'd
i'll
i'm
i've
imho
inducers
it'd
khan
@ -86,6 +91,7 @@ privs
propping
psi
pst
quid
refit
refitting
replicator
@ -115,6 +121,7 @@ starfleet
starship
straightening
stunted
tarred
terrence
they're
turbolift
@ -126,6 +133,7 @@ url
utne
valen
veni
wasn't
we'll
we're
we've

View File

@ -0,0 +1,26 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.iface;
import com.silverwrist.dynamo.except.DatabaseException;
public interface UniStore
{
public UniStoreMessage getMessage(long msgid) throws DatabaseException;
} // end interface UniStore

View File

@ -18,13 +18,14 @@
package com.silverwrist.dynamo.iface;
import java.io.Reader;
import com.silverwrist.dynamo.except.DatabaseException;
public interface UniStoreTextPart extends UniStorePart
{
public int getLineCount();
public String getText();
public String getText() throws DatabaseException;
public Reader getTextAsReader();
public Reader getTextAsReader() throws DatabaseException;
} // end interface UniStoreTextPart

View File

@ -0,0 +1,454 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.io.*;
import java.sql.Blob;
import java.sql.SQLException;
import java.util.*;
import org.apache.commons.collections.*;
import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class BinaryPartImpl implements UniStoreBinaryPart
{
/*--------------------------------------------------------------------------------
* Internal class implementing a Blob return
*--------------------------------------------------------------------------------
*/
private class ReturnBlob implements Blob
{
/*====================================================================
* Attributes
*====================================================================
*/
private byte[] m_data; // the actual blob data
/*====================================================================
* Constructor
*====================================================================
*/
ReturnBlob(byte[] data)
{
m_data = data;
} // end constructor
/*====================================================================
* Implementations from interface Blob
*====================================================================
*/
public long length()
{
return m_size;
} // end length
public byte[] getBytes(long pos, int length) throws SQLException
{
if ((pos<1) || (pos>(long)m_size))
throw new SQLException("invalid position value");
if ((length<=0) || ((pos + length - 1)>(long)m_size))
throw new SQLException("invalid length value");
byte[] rc = new byte[length];
System.arraycopy(m_data,(int)pos,rc,0,length);
return rc;
} // end getBytes
public InputStream getBinaryStream()
{
return new ByteArrayInputStream(m_data);
} // end getBinaryStream
public long position(byte[] pattern, long start) throws SQLException
{
throw new SQLException("position() method not implemented");
} // end position
public long position(Blob pattern, long start) throws SQLException
{
throw new SQLException("position() method not implemented");
} // end position
public int setBytes(long pos, byte[] bytes) throws SQLException
{
throw new SQLException("setBytes() method not implemented");
} // end setBytes
public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException
{
throw new SQLException("setBytes() method not implemented");
} // end setBytes
public OutputStream setBinaryStream(long pos) throws SQLException
{
throw new SQLException("setBinaryStream() method not implemented");
} // end setBinaryStream
public void truncate(long len) throws SQLException
{
throw new SQLException("truncate() method not implemented");
} // end truncate
} // end class ReturnBlob
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private BinaryPartOps m_ops;
private NamespaceCache m_nscache;
private MessageImpl m_parent;
private int m_part;
private QualifiedNameKey m_identity;
private String m_mimetype;
private int m_size;
private String m_filename;
private int m_nread;
private java.util.Date m_lastread;
private ReferenceMap m_properties;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
BinaryPartImpl(BinaryPartOps ops, NamespaceCache nscache, MessageImpl parent, Map params) throws DatabaseException
{
m_ops = ops;
m_nscache = nscache;
m_parent = parent;
m_part = ((Integer)(params.get(MessageOps.PARAM_PART))).intValue();
PropertyKey pk = (PropertyKey)(params.get(MessageOps.PARAM_IDENTITY));
m_identity = new QualifiedNameKey(nscache.namespaceIdToName(pk.getNamespaceID()),pk.getName());
m_mimetype = (String)(params.get(MessageOps.PARAM_MIMETYPE));
Integer tmp = (Integer)(params.get(MessageOps.PARAM_SIZE));
if (tmp!=null)
m_size = tmp.intValue();
m_filename = (String)(params.get(MessageOps.PARAM_FILENAME));
m_nread = ((Integer)(params.get(MessageOps.PARAM_READS))).intValue();
m_lastread = (java.util.Date)(params.get(MessageOps.PARAM_LASTREAD));
m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectProvider
*--------------------------------------------------------------------------------
*/
/**
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be retrieved.
* @return The object reference specified.
*/
public Object getObject(String namespace, String name)
{
try
{ // convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
Object rc = null;
synchronized (this)
{ // start by looking in the properties map
rc = m_properties.get(key);
if (rc==null)
{ // no use - need to try the database
rc = m_ops.getProperty(m_parent.getMessageID(),m_part,key);
if (rc!=null)
m_properties.put(key,rc);
} // end if
} // end synchronized block
if (rc==null)
throw new NoSuchObjectException(this.toString(),namespace,name);
return rc;
} // end try
catch (DatabaseException e)
{ // translate into our NoSuchObjectException but retain the DatabaseException
throw new NoSuchObjectException(this.toString(),namespace,name,e);
} // end catch
} // end getObject
/*--------------------------------------------------------------------------------
* Implementations from interface SecureObjectStore
*--------------------------------------------------------------------------------
*/
/**
* Sets an object into this <CODE>SecureObjectStore</CODE>.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be set.
* @param value The object to set into the <CODE>SecureObjectStore</CODE>.
* @return The previous object that was set into the <CODE>SecureObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error setting the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* set this object value into this <CODE>SecureObjectStore</CODE>.
*/
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
throws DatabaseException, DynamoSecurityException
{
m_parent.testPermission(caller,namespace,"set.property","no.setProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by setting the database value
rc = m_ops.setProperty(m_parent.getMessageID(),m_part,key,value);
// and cache it, too
m_properties.put(key,value);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end setObject
/**
* Removes an object from this <CODE>SecureObjectStore</CODE>.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be removed.
* @return The previous object that was set into the <CODE>SecureObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error removing the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* remove this object value from this <CODE>SecureObjectStore</CODE>.
*/
public Object removeObject(DynamoUser caller, String namespace, String name)
throws DatabaseException, DynamoSecurityException
{
m_parent.testPermission(caller,namespace,"remove.property","no.removeProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by killing the database value
rc = m_ops.removeProperty(m_parent.getMessageID(),m_part,key);
// and remove the cached value, too
m_properties.remove(key);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end removeObject
/**
* Returns a collection of all object namespaces that have been set into this <CODE>SecureObjectStore</CODE>.
*
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects specifying
* all the object namespaces.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the namespace list.
*/
public Collection getNamespaces() throws DatabaseException
{
// call through to the database to get the list of namespace IDs
int[] ids = m_ops.getPropertyNamespaceIDs(m_parent.getMessageID(),m_part);
ArrayList rc = new ArrayList(ids.length);
for (int i=0; i<ids.length; i++)
rc.add(m_nscache.namespaceIdToName(ids[i]));
return Collections.unmodifiableList(rc);
} // end getNamespaces
/**
* Returns a collection of all object names that have been set into this <CODE>SecureObjectStore</CODE> under
* a given namespace.
*
* @param namespace The namespace to look for names under.
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects
* specifying all the object names for this namespace.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the object name list.
*/
public Collection getNamesForNamespace(String namespace) throws DatabaseException
{
// call through to the database to get the data for this namespace
int nsid = m_nscache.namespaceNameToId(namespace);
Map data = m_ops.getAllProperties(m_parent.getMessageID(),m_part,nsid);
// we both create the return value and cache the data values
ArrayList rc = new ArrayList(data.size());
synchronized (this)
{ // do the transfer...
Iterator it = data.entrySet().iterator();
while (it.hasNext())
{ // copy one entry at a time
Map.Entry ntry = (Map.Entry)(it.next());
rc.add(ntry.getKey().toString());
m_properties.put(new PropertyKey(nsid,ntry.getKey().toString()),ntry.getValue());
} // end while
} // end synchronized block
return Collections.unmodifiableList(rc);
} // end getNamesForNamespace
/*--------------------------------------------------------------------------------
* Implementations from interface UniStorePart
*--------------------------------------------------------------------------------
*/
public long getMessageID()
{
return m_parent.getMessageID();
} // end getMessageID
public int getPartIndex()
{
return m_part;
} // end getPartIndex
public QualifiedNameKey getPartIdentity()
{
return m_identity;
} // end getPartIdentity
public String getMimeType()
{
return m_mimetype;
} // end getMimeType
public int getSize()
{
return m_size;
} // end getSize
public int getNumReads()
{
return m_nread;
} // end getNumReads
public java.util.Date getLastReadDate()
{
return m_lastread;
} // end getLastReadDate
public void touchRead() throws DatabaseException
{
synchronized (this)
{ // touch the database, then the local values
java.util.Date tmp = m_ops.touchRead(m_parent.getMessageID(),m_part);
m_nread++;
m_lastread = tmp;
} // end synchronized block
// TODO: post an update?
} // end touchRead
/*--------------------------------------------------------------------------------
* Implementations from interface DataItem
*--------------------------------------------------------------------------------
*/
public String getName()
{
return m_filename;
} // end getName
public InputStream getDataStream() throws IOException
{
try
{ // call through to the database to get the data stream
return m_ops.getData(m_parent.getMessageID(),m_part);
} // end try
catch (DatabaseException e)
{ // create an IOException and chain this one onto it
IOException ioe = new IOException("Database error retrieving data stream");
ioe.initCause(e);
throw ioe;
} // end catch
} // end getDataStream
public Blob getBlob() throws SQLException
{
try
{ // load the data from the database and create the Blob around it
byte[] data = new byte[m_size];
m_ops.getData(m_parent.getMessageID(),m_part,data);
return new ReturnBlob(data);
} // end try
catch (DatabaseException e)
{ // create a SQLException and chain this one onto it
SQLException se = new SQLException("Database error retrieving data stream");
se.initCause(e);
throw se;
} // end catch
catch (IOException e)
{ // create a SQLException and chain this one onto it
SQLException se = new SQLException("I/O error retrieving data stream");
se.initCause(e);
throw se;
} // end catch
} // end getBlob
/*--------------------------------------------------------------------------------
* Implementations from interface UniStoreBinaryPart
*--------------------------------------------------------------------------------
*/
} // end class BinaryPartImpl

View File

@ -0,0 +1,62 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.io.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
abstract class BinaryPartOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected BinaryPartOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
abstract Object getProperty(long msgid, int part, PropertyKey key) throws DatabaseException;
abstract Object setProperty(long msgid, int part, PropertyKey key, Object value) throws DatabaseException;
abstract Object removeProperty(long msgid, int part, PropertyKey key) throws DatabaseException;
abstract int[] getPropertyNamespaceIDs(long msgid, int part) throws DatabaseException;
abstract Map getAllProperties(long msgid, int part, int namespace) throws DatabaseException;
abstract java.util.Date touchRead(long msgid, int part) throws DatabaseException;
abstract CacheInputStream getData(long msgid, int part) throws IOException, DatabaseException;
abstract int getData(long msgid, int part, byte[] here) throws IOException, DatabaseException;
} // end class BinaryPartOps

View File

@ -0,0 +1,506 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.io.*;
import java.sql.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class BinaryPartOps_mysql extends BinaryPartOps
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private PropertySerializer m_psz; // reference to property serializer
private DBUtilities m_utils;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
BinaryPartOps_mysql(DBConnectionPool pool)
{
super(pool);
m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class));
m_utils = (DBUtilities)(pool.queryService(DBUtilities.class));
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class OpsBase
*--------------------------------------------------------------------------------
*/
public void dispose()
{
m_psz = null;
m_utils = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract implementations from class BinaryPartOps
*--------------------------------------------------------------------------------
*/
Object getProperty(long msgid, int part, PropertyKey key) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String rc_str = null;
try
{ // get a connection
conn = getConnection();
// look up the property
stmt = conn.prepareStatement("SELECT prop_value FROM us_binary_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (!(rs.next()))
return null; // property not found
rc_str = rs.getString(1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(rc_str);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end getProperty
Object setProperty(long msgid, int part, PropertyKey key, Object value) throws DatabaseException
{
String serialized_value = m_psz.serializeProperty(value);
if (serialized_value==null)
{ // serialization exception - throw it
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages","property.serialize");
de.setParameter(0,key.getName());
throw de;
} // end if
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_binary_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_binary_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
if (old_value!=null)
{ // prepare the statement to update the existing record
stmt = conn.prepareStatement("UPDATE us_binary_prop SET prop_value = ? WHERE msgid = ? AND part = ? "
+ "AND nsid = ? AND prop_name = ?;");
stmt.setString(1,serialized_value);
stmt.setLong(2,msgid);
stmt.setInt(3,part);
stmt.setInt(4,key.getNamespaceID());
stmt.setString(5,key.getName());
} // end if
else
{ // prepare the statement to insert a new record
stmt = conn.prepareStatement("INSERT INTO us_binary_prop (msgid, part, nsid, prop_name, prop_value) "
+ "VALUES (?, ?, ?, ?, ?);");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
stmt.setString(5,serialized_value);
} // end else
stmt.executeUpdate(); // execute it!
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
if (old_value==null)
return null; // no previous value
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end setProperty
Object removeProperty(long msgid, int part, PropertyKey key) throws DatabaseException
{
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_binary_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_binary_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
else
return null; // no need to remove anything
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
// delete the database row
stmt = conn.prepareStatement("DELETE FROM us_binary_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end removeProperty
int[] getPropertyNamespaceIDs(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM us_binary_prop WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
rs = stmt.executeQuery();
// read out a list of the namespace IDs
ArrayList tmp = new ArrayList();
while (rs.next())
tmp.add(new Integer(rs.getInt(1)));
// create and return the array
int[] rc = new int[tmp.size()];
for (int i=0; i<tmp.size(); i++)
rc[i] = ((Integer)(tmp.get(i))).intValue();
tmp.clear();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getPropertyNamespaceIDs
Map getAllProperties(long msgid, int part, int namespace) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT prop_name, prop_value FROM us_binary_prop WHERE msgid = ? AND part = ? "
+ "AND nsid = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,namespace);
rs = stmt.executeQuery();
// prepare the return value
HashMap rc = new HashMap();
while (rs.next())
{ // copy data out, deserializing properties as we go
String key = rs.getString(1);
Object value = m_psz.deserializeProperty(rs.getString(2));
if (value==null)
{ // deserialization exception - throw it
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages",
"property.deserialize");
de.setParameter(0,key);
throw de;
} // end if
rc.put(key,value);
} // end while
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getAllProperties
java.util.Date touchRead(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_binary WRITE;");
// prepare and execute the statement
stmt = conn.prepareStatement("UPDATE us_binary SET reads = reads + 1, lastread = ? WHERE msgid = ? "
+ "AND part = ?;");
java.util.Date rc = new java.util.Date();
m_utils.setDateTime(stmt,1,rc);
stmt.setLong(2,msgid);
stmt.setInt(3,part);
stmt.executeUpdate();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end touchRead
CacheInputStream getData(long msgid, int part) throws IOException, DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT data FROM us_binary WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setLong(2,part);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages",
"bad.loadBinary.part");
de.setParameter(0,String.valueOf(part));
de.setParameter(1,String.valueOf(msgid));
throw de;
} // end if
// Create the return value.
return new CacheInputStream("bin-" + msgid + "-" + part,rs.getBinaryStream(1));
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getData
int getData(long msgid, int part, byte[] here) throws IOException, DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT data FROM us_binary WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setLong(2,part);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(BinaryPartOps_mysql.class,"UniStoreMessages",
"bad.loadBinary.part");
de.setParameter(0,String.valueOf(part));
de.setParameter(1,String.valueOf(msgid));
throw de;
} // end if
// Copy the return data.
InputStream stm = rs.getBinaryStream(1);
return stm.read(here);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getData
} // end class BinaryPartOps_mysql

View File

@ -0,0 +1,104 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.util.*;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
abstract class ManagerOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
static final String PARAM_MSGID = "msgid";
static final String PARAM_PARENT = "parent";
static final String PARAM_SEQ = "seq";
static final String PARAM_CREATOR = "creator";
static final String PARAM_POSTED = "posted";
static final String PARAM_ACLID = "aclid";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private MessageOps m_msgops = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected ManagerOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class OpsBase
*--------------------------------------------------------------------------------
*/
public void dispose()
{
if (m_msgops!=null)
m_msgops.dispose();
m_msgops = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
protected abstract MessageOps createMessageOps(DBConnectionPool pool);
abstract Map getMessageData(long msgid) throws DatabaseException;
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
synchronized MessageOps getMessageOps()
{
if (m_msgops==null)
m_msgops = createMessageOps(getPool());
return m_msgops;
} // return getMessageOps
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
static ManagerOps get(DBConnectionPool pool) throws ConfigException
{
return (ManagerOps)get(pool,ManagerOps.class.getClassLoader(),ManagerOps.class.getName() + "_","ManagerOps");
} // end get
} // end class ManagerOps

View File

@ -0,0 +1,119 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.sql.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class ManagerOps_mysql extends ManagerOps
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DBUtilities m_utils;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public ManagerOps_mysql(DBConnectionPool pool)
{
super(pool);
m_utils = (DBUtilities)(pool.queryService(DBUtilities.class));
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class ManagerOps
*--------------------------------------------------------------------------------
*/
public void dispose()
{
m_utils = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract implementations from class ManagerOps
*--------------------------------------------------------------------------------
*/
protected MessageOps createMessageOps(DBConnectionPool pool)
{
return new MessageOps_mysql(pool);
} // end createMessageOps
Map getMessageData(long msgid) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// prepare and execute a statement to find the header data
stmt = conn.prepareStatement("SELECT parent, seq, creator, posted, aclid FROM us_head WHERE msgid = ?;");
stmt.setLong(1,msgid);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // the message was not found
DatabaseException de = new DatabaseException(ManagerOps_mysql.class,"UniStoreMessages","no.message");
de.setParameter(0,String.valueOf(msgid));
throw de;
} // end if
// build the return value
HashMap rc = new HashMap();
rc.put(PARAM_MSGID,new Long(msgid));
rc.put(PARAM_PARENT,new Long(rs.getLong(1)));
rc.put(PARAM_SEQ,new Integer(rs.getInt(2)));
rc.put(PARAM_CREATOR,new Integer(rs.getInt(3)));
rc.put(PARAM_POSTED,m_utils.getDateTime(rs,4));
int tmp = rs.getInt(5);
if (!(rs.wasNull()))
rc.put(PARAM_ACLID,new Integer(tmp));
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getMessageData
} // end class ManagerOps_mysql

View File

@ -0,0 +1,567 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.security.acl.AclNotFoundException;
import java.util.*;
import org.apache.commons.collections.*;
import org.apache.log4j.Logger;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.db.UserManagement;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.security.SecurityReferenceMonitor;
import com.silverwrist.dynamo.util.*;
class MessageImpl implements UniStoreMessage
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(MessageImpl.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private MessageOps m_ops; // database operations object
private NamespaceCache m_nscache; // namespace cache
private SecurityReferenceMonitor m_srm; // security reference monitor
private UserManagement m_users; // user manager
private long m_id; // the message ID
private long m_parentid; // the parent message ID
private int m_seq; // sequence within parent
private int m_creator; // UID of creator
private java.util.Date m_posted; // date message was posted
private int m_aclid = -1; // ACL id
private ReferenceMap m_properties; // properties cache
private int m_text_count = -1; // number of text parts
private int m_binary_count = -1; // number of binary parts
private ReferenceMap m_part_to_text; // mapping from part index to text part
private ReferenceMap m_pk_to_text; // mapping from property key to text part
private ReferenceMap m_part_to_binary; // mapping from part index to binary part
private ReferenceMap m_pk_to_binary; // mapping from property key to binary part
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
MessageImpl(MessageOps ops, NamespaceCache nscache, SecurityReferenceMonitor srm, UserManagement users, Map params)
{
m_ops = ops;
m_nscache = nscache;
m_srm = srm;
m_users = users;
m_id = ((Long)(params.get(ManagerOps.PARAM_MSGID))).longValue();
m_parentid = ((Long)(params.get(ManagerOps.PARAM_PARENT))).longValue();
m_seq = ((Integer)(params.get(ManagerOps.PARAM_SEQ))).intValue();
m_creator = ((Integer)(params.get(ManagerOps.PARAM_CREATOR))).intValue();
m_posted = (java.util.Date)(params.get(ManagerOps.PARAM_POSTED));
Integer tmp = (Integer)(params.get(ManagerOps.PARAM_ACLID));
if (tmp!=null)
m_aclid = tmp.intValue();
m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
m_part_to_text = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
m_pk_to_text = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
m_part_to_binary = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
m_pk_to_binary = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectProvider
*--------------------------------------------------------------------------------
*/
/**
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be retrieved.
* @return The object reference specified.
*/
public Object getObject(String namespace, String name)
{
try
{ // convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
Object rc = null;
synchronized (this)
{ // start by looking in the properties map
rc = m_properties.get(key);
if (rc==null)
{ // no use - need to try the database
rc = m_ops.getProperty(m_id,key);
if (rc!=null)
m_properties.put(key,rc);
} // end if
} // end synchronized block
if (rc==null)
throw new NoSuchObjectException(this.toString(),namespace,name);
return rc;
} // end try
catch (DatabaseException e)
{ // translate into our NoSuchObjectException but retain the DatabaseException
throw new NoSuchObjectException(this.toString(),namespace,name,e);
} // end catch
} // end getObject
/*--------------------------------------------------------------------------------
* Implementations from interface SecureObjectStore
*--------------------------------------------------------------------------------
*/
/**
* Sets an object into this message's properties.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be set.
* @param value The object to set into the message's properties.
* @return The previous object that was set into the message's properties under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error setting the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* set this object value into this message's properties.
*/
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
throws DatabaseException, DynamoSecurityException
{
testPermission(caller,namespace,"set.property","no.setProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by setting the database value
rc = m_ops.setProperty(m_id,key,value);
// and cache it, too
m_properties.put(key,value);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end setObject
/**
* Removes an object from this message's properties.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be removed.
* @return The previous object that was set into the message's properties under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error removing the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* remove this object value from this message's properties.
*/
public Object removeObject(DynamoUser caller, String namespace, String name)
throws DatabaseException, DynamoSecurityException
{
testPermission(caller,namespace,"remove.property","no.removeProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by killing the database value
rc = m_ops.removeProperty(m_id,key);
// and remove the cached value, too
m_properties.remove(key);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end removeObject
/**
* Returns a collection of all object namespaces that have been set into this message's properties.
*
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects specifying
* all the object namespaces.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the namespace list.
*/
public Collection getNamespaces() throws DatabaseException
{
// call through to the database to get the list of namespace IDs
int[] ids = m_ops.getPropertyNamespaceIDs(m_id);
ArrayList rc = new ArrayList(ids.length);
for (int i=0; i<ids.length; i++)
rc.add(m_nscache.namespaceIdToName(ids[i]));
return Collections.unmodifiableList(rc);
} // end getNamespaces
/**
* Returns a collection of all object names that have been set into this message's properties under
* a given namespace.
*
* @param namespace The namespace to look for names under.
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects
* specifying all the object names for this namespace.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the object name list.
*/
public Collection getNamesForNamespace(String namespace) throws DatabaseException
{
// call through to the database to get the data for this namespace
int nsid = m_nscache.namespaceNameToId(namespace);
Map data = m_ops.getAllProperties(m_id,nsid);
// we both create the return value and cache the data values
ArrayList rc = new ArrayList(data.size());
synchronized (this)
{ // do the transfer...
Iterator it = data.entrySet().iterator();
while (it.hasNext())
{ // copy one entry at a time
Map.Entry ntry = (Map.Entry)(it.next());
rc.add(ntry.getKey().toString());
m_properties.put(new PropertyKey(nsid,ntry.getKey().toString()),ntry.getValue());
} // end while
} // end synchronized block
return Collections.unmodifiableList(rc);
} // end getNamesForNamespace
/*--------------------------------------------------------------------------------
* Implementations from interface UniStoreMessage
*--------------------------------------------------------------------------------
*/
public long getMessageID()
{
return m_id;
} // end getMessageID
public long getParentMessageID()
{
return m_parentid;
} // end getParentMessageID
public void setParentMessageID(DynamoUser caller, long id) throws DatabaseException, DynamoSecurityException
{
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"set.parent","no.setParent");
synchronized (this)
{ // reset the parent message ID
m_ops.setParentMessageID(m_id,id);
m_parentid = id;
} // end synchronized block
// TODO: send out an update?
} // end setParentMessageID
public int getSequence()
{
return m_seq;
} // end getSequence
public void setSequence(DynamoUser caller, int seq) throws DatabaseException, DynamoSecurityException
{
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"set.parent","no.setParent");
synchronized (this)
{ // reset the sequence number
m_ops.setSequence(m_id,seq);
m_seq = seq;
} // end if
// TODO: send out an update?
} // end setSequence
public int getCreatorUID()
{
return m_creator;
} // end getCreatorUID
public DynamoUser getCreator() throws DatabaseException
{
return m_users.getUser(m_creator);
} // end getCreator
public java.util.Date getPostDate()
{
return m_posted;
} // end getPostDate
public DynamoAcl getAcl() throws DatabaseException, AclNotFoundException
{
return m_srm.getAcl(m_aclid);
} // end getAcl
public void setAcl(DynamoUser caller, DynamoAcl acl) throws DatabaseException, DynamoSecurityException
{
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"set.ACL","no.setACL");
int aclid = -1;
if (acl!=null)
aclid = acl.getAclID();
synchronized (this)
{ // reset the ACL ID
m_ops.setAclID(m_id,aclid);
m_aclid = aclid;
} // end synchronized block
// TODO: post an update?
} // end setAcl
public synchronized int getNumTextParts() throws DatabaseException
{
if (m_text_count<0)
m_text_count = m_ops.getNumTextParts(m_id);
return m_text_count;
} // end getNumTextParts
public synchronized int getNumBinaryParts() throws DatabaseException
{
if (m_binary_count<0)
m_binary_count = m_ops.getNumBinaryParts(m_id);
return m_binary_count;
} // end getNumBinaryParts
public UniStoreTextPart getTextPart(int index) throws DatabaseException
{
Integer key = new Integer(index);
TextPartImpl rc = null;
synchronized (this)
{ // look in the part-to-text map first
rc = (TextPartImpl)(m_part_to_text.get(key));
if (rc==null)
{ // OK, look up the part in the database
Map params = m_ops.loadTextPart(m_id,index);
PropertyKey otherkey = (PropertyKey)(params.get(MessageOps.PARAM_IDENTITY));
rc = (TextPartImpl)(m_pk_to_text.get(otherkey));
if (rc==null)
{ // need to create a new object
rc = new TextPartImpl(m_ops.getTextPartOps(),m_nscache,this,params);
m_part_to_text.put(key,rc);
m_pk_to_text.put(otherkey,rc);
} // end if
else // feed back into the parts map
m_part_to_text.put(key,rc);
} // end if
else
{ // need to reinsert into property key map
QualifiedNameKey qnk = rc.getPartIdentity();
PropertyKey pk = new PropertyKey(m_nscache.namespaceNameToId(qnk.getNamespace()),qnk.getName());
m_pk_to_text.put(pk,rc);
} // end else
} // end synchronized block
return rc;
} // end getTextPart
public UniStoreTextPart getTextPart(String namespace, String name) throws DatabaseException
{
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
TextPartImpl rc = null;
synchronized (this)
{ // look in the PK-to-text map first
rc = (TextPartImpl)(m_pk_to_text.get(key));
if (rc==null)
{ // OK, look up the part in the database
Map params = m_ops.loadTextPart(m_id,key);
Integer otherkey = (Integer)(params.get(MessageOps.PARAM_PART));
rc = (TextPartImpl)(m_part_to_text.get(otherkey));
if (rc==null)
{ // OK, need to create the object
rc = new TextPartImpl(m_ops.getTextPartOps(),m_nscache,this,params);
m_part_to_text.put(otherkey,rc);
m_pk_to_text.put(key,rc);
} // end if
else // feed back into the PKs map
m_pk_to_text.put(key,rc);
} // end if
else // reinsert into part key map
m_part_to_text.put(new Integer(rc.getPartIndex()),rc);
} // end synchronized block
return rc;
} // end getTextPart
public UniStoreBinaryPart getBinaryPart(int index) throws DatabaseException
{
Integer key = new Integer(index);
BinaryPartImpl rc = null;
synchronized (this)
{ // look in the part-to-binary map first
rc = (BinaryPartImpl)(m_part_to_binary.get(key));
if (rc==null)
{ // OK, look up the part in the database
Map params = m_ops.loadBinaryPart(m_id,index);
PropertyKey otherkey = (PropertyKey)(params.get(MessageOps.PARAM_IDENTITY));
rc = (BinaryPartImpl)(m_pk_to_binary.get(otherkey));
if (rc==null)
{ // need to create a new object
rc = new BinaryPartImpl(m_ops.getBinaryPartOps(),m_nscache,this,params);
m_part_to_binary.put(key,rc);
m_pk_to_binary.put(otherkey,rc);
} // end if
else // feed back into the parts map
m_part_to_binary.put(key,rc);
} // end if
else
{ // need to reinsert into property key map
QualifiedNameKey qnk = rc.getPartIdentity();
PropertyKey pk = new PropertyKey(m_nscache.namespaceNameToId(qnk.getNamespace()),qnk.getName());
m_pk_to_binary.put(pk,rc);
} // end else
} // end synchronized block
return rc;
} // end getBinaryPart
public UniStoreBinaryPart getBinaryPart(String namespace, String name) throws DatabaseException
{
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
BinaryPartImpl rc = null;
synchronized (this)
{ // look in the PK-to-binary map first
rc = (BinaryPartImpl)(m_pk_to_binary.get(key));
if (rc==null)
{ // OK, look up the part in the database
Map params = m_ops.loadBinaryPart(m_id,key);
Integer otherkey = (Integer)(params.get(MessageOps.PARAM_PART));
rc = (BinaryPartImpl)(m_part_to_binary.get(otherkey));
if (rc==null)
{ // OK, need to create the object
rc = new BinaryPartImpl(m_ops.getBinaryPartOps(),m_nscache,this,params);
m_part_to_binary.put(otherkey,rc);
m_pk_to_binary.put(key,rc);
} // end if
else // feed back into the PKs map
m_pk_to_binary.put(key,rc);
} // end if
else // reinsert into part key map
m_part_to_binary.put(new Integer(rc.getPartIndex()),rc);
} // end synchronized block
return rc;
} // end getBinaryPart
public List getTextParts() throws DatabaseException
{
int n = this.getNumTextParts();
ArrayList rc = new ArrayList(n);
for (int i=1; i<=n; i++)
rc.add(this.getTextPart(i));
return Collections.unmodifiableList(rc);
} // end getTextParts
public List getBinaryParts() throws DatabaseException
{
int n = this.getNumBinaryParts();
ArrayList rc = new ArrayList(n);
for (int i=1; i<=n; i++)
rc.add(this.getBinaryPart(i));
return Collections.unmodifiableList(rc);
} // end getBinaryParts
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
void testPermission(DynamoUser caller, String perm_namespace, String perm_name, String fail_message)
throws DatabaseException, DynamoSecurityException
{
if (caller.equals(m_srm.getAdminUser()))
return; // Administrator can do anything
if (m_aclid==-1)
{ // no ACL - rely on fallback method
if (caller.getUID()==m_creator)
return; // the creator can do anything, but no one else can
} // end if
else
{ // test against the ACL
try
{ // look up the ACL
if (m_srm.getAcl(m_aclid).testPermission(caller,perm_namespace,perm_name))
return;
} // end try
catch (AclNotFoundException e)
{ // ACL not found - go to fallback mechanism
logger.warn("ACL " + m_aclid + " not found while testing message " + m_id);
if (caller.getUID()==m_creator)
return; // the creator can do anything, but no one else can
} // end catch
} // end else
// Throw a DynamoSecurityException indicating what you're not permitted to do.
DynamoSecurityException de = new DynamoSecurityException(MessageImpl.class,"UniStoreMessages",fail_message);
de.setParameter(0,String.valueOf(m_id));
throw de;
} // end testPermission
} // end class MessageImpl

View File

@ -0,0 +1,136 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.util.*;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
abstract class MessageOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
static final String PARAM_PART = "part";
static final String PARAM_IDENTITY = "identity";
static final String PARAM_MIMETYPE = "mimetype";
static final String PARAM_SIZE = "size";
static final String PARAM_LINECOUNT = "linecount";
static final String PARAM_READS = "reads";
static final String PARAM_LASTREAD = "lastread";
static final String PARAM_FILENAME = "filename";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private TextPartOps m_textops = null;
private BinaryPartOps m_binaryops = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected MessageOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class OpsBase
*--------------------------------------------------------------------------------
*/
public void dispose()
{
if (m_textops!=null)
m_textops.dispose();
m_textops = null;
if (m_binaryops!=null)
m_binaryops.dispose();
m_binaryops = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
protected abstract TextPartOps createTextPartOps(DBConnectionPool pool);
protected abstract BinaryPartOps createBinaryPartOps(DBConnectionPool pool);
abstract Object getProperty(long msgid, PropertyKey key) throws DatabaseException;
abstract Object setProperty(long msgid, PropertyKey key, Object value) throws DatabaseException;
abstract Object removeProperty(long msgid, PropertyKey key) throws DatabaseException;
abstract int[] getPropertyNamespaceIDs(long msgid) throws DatabaseException;
abstract Map getAllProperties(long msgid, int namespace) throws DatabaseException;
abstract void setParentMessageID(long msgid, long parent) throws DatabaseException;
abstract void setSequence(long msgid, int seq) throws DatabaseException;
abstract void setAclID(long msgid, int aclid) throws DatabaseException;
abstract int getNumTextParts(long msgid) throws DatabaseException;
abstract int getNumBinaryParts(long msgid) throws DatabaseException;
abstract Map loadTextPart(long msgid, int part) throws DatabaseException;
abstract Map loadTextPart(long msgid, PropertyKey identity) throws DatabaseException;
abstract Map loadBinaryPart(long msgid, int part) throws DatabaseException;
abstract Map loadBinaryPart(long msgid, PropertyKey identity) throws DatabaseException;
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
synchronized TextPartOps getTextPartOps()
{
if (m_textops==null)
m_textops = createTextPartOps(getPool());
return m_textops;
} // end getTextPartOps
synchronized BinaryPartOps getBinaryPartOps()
{
if (m_binaryops==null)
m_binaryops = createBinaryPartOps(getPool());
return m_binaryops;
} // end getBinaryPartOps
} // end class MessageOps

View File

@ -0,0 +1,793 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.sql.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class MessageOps_mysql extends MessageOps
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private PropertySerializer m_psz; // reference to property serializer
private DBUtilities m_utils;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
MessageOps_mysql(DBConnectionPool pool)
{
super(pool);
m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class));
m_utils = (DBUtilities)(pool.queryService(DBUtilities.class));
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class MessageOps
*--------------------------------------------------------------------------------
*/
public void dispose()
{
m_psz = null;
m_utils = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
protected TextPartOps createTextPartOps(DBConnectionPool pool)
{
return new TextPartOps_mysql(pool);
} // end createTextPartOps
protected BinaryPartOps createBinaryPartOps(DBConnectionPool pool)
{
return new BinaryPartOps_mysql(pool);
} // end createBinaryPartOps
Object getProperty(long msgid, PropertyKey key) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String rc_str = null;
try
{ // get a connection
conn = getConnection();
// look up the property
stmt = conn.prepareStatement("SELECT prop_value FROM us_prop WHERE msgid = ? AND nsid = ? AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,key.getNamespaceID());
stmt.setString(3,key.getName());
rs = stmt.executeQuery();
if (!(rs.next()))
return null; // property not found
rc_str = rs.getString(1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(rc_str);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end getProperty
Object setProperty(long msgid, PropertyKey key, Object value) throws DatabaseException
{
String serialized_value = m_psz.serializeProperty(value);
if (serialized_value==null)
{ // serialization exception - throw it
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","property.serialize");
de.setParameter(0,key.getName());
throw de;
} // end if
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_prop WHERE msgid = ? AND nsid = ? AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,key.getNamespaceID());
stmt.setString(3,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
if (old_value!=null)
{ // prepare the statement to update the existing record
stmt = conn.prepareStatement("UPDATE us_prop SET prop_value = ? WHERE msgid = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setString(1,serialized_value);
stmt.setLong(2,msgid);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
} // end if
else
{ // prepare the statement to insert a new record
stmt = conn.prepareStatement("INSERT INTO us_prop (msgid, nsid, prop_name, prop_value) VALUES (?, ?, ?, ?);");
stmt.setLong(1,msgid);
stmt.setInt(2,key.getNamespaceID());
stmt.setString(3,key.getName());
stmt.setString(4,serialized_value);
} // end else
stmt.executeUpdate(); // execute it!
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
if (old_value==null)
return null; // no previous value
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end setProperty
Object removeProperty(long msgid, PropertyKey key) throws DatabaseException
{
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_prop WHERE msgid = ? AND nsid = ? AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,key.getNamespaceID());
stmt.setString(3,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
else
return null; // no need to remove anything
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
// delete the database row
stmt = conn.prepareStatement("DELETE FROM us_prop WHERE msgid = ? AND nsid = ? AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,key.getNamespaceID());
stmt.setString(3,key.getName());
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end removeProperty
int[] getPropertyNamespaceIDs(long msgid) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM us_prop WHERE msgid = ?;");
stmt.setLong(1,msgid);
rs = stmt.executeQuery();
// read out a list of the namespace IDs
ArrayList tmp = new ArrayList();
while (rs.next())
tmp.add(new Integer(rs.getInt(1)));
// create and return the array
int[] rc = new int[tmp.size()];
for (int i=0; i<tmp.size(); i++)
rc[i] = ((Integer)(tmp.get(i))).intValue();
tmp.clear();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getPropertyNamespaceIDs
Map getAllProperties(long msgid, int namespace) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT prop_name, prop_value FROM us_prop WHERE msgid = ? AND nsid = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,namespace);
rs = stmt.executeQuery();
// prepare the return value
HashMap rc = new HashMap();
while (rs.next())
{ // copy data out, deserializing properties as we go
String key = rs.getString(1);
Object value = m_psz.deserializeProperty(rs.getString(2));
if (value==null)
{ // deserialization exception - throw it
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages",
"property.deserialize");
de.setParameter(0,key);
throw de;
} // end if
rc.put(key,value);
} // end while
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getAllProperties
void setParentMessageID(long msgid, long parent) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_head WRITE;");
// update the parent field
stmt = conn.prepareStatement("UPDATE us_head SET parent = ? WHERE msgid = ?;");
stmt.setLong(1,parent);
stmt.setLong(2,msgid);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end try
void setSequence(long msgid, int seq) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_head WRITE;");
// update the sequence field
stmt = conn.prepareStatement("UPDATE us_head SET seq = ? WHERE msgid = ?;");
stmt.setInt(1,seq);
stmt.setLong(2,msgid);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end setSequence
void setAclID(long msgid, int aclid) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_head WRITE;");
// update the ACL ID field
stmt = conn.prepareStatement("UPDATE us_head SET aclid = ? WHERE msgid = ?;");
if (aclid<=0)
stmt.setNull(1,Types.INTEGER);
else
stmt.setInt(1,aclid);
stmt.setLong(2,msgid);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end setAclID
int getNumTextParts(long msgid) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT COUNT(*) FROM us_text WHERE msgid = ?;");
stmt.setLong(1,msgid);
rs = stmt.executeQuery();
return SQLUtils.getReturnCountInt(rs,1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getNumTextParts
int getNumBinaryParts(long msgid) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT COUNT(*) FROM us_binary WHERE msgid = ?;");
stmt.setLong(1,msgid);
rs = stmt.executeQuery();
return SQLUtils.getReturnCountInt(rs,1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getNumBinaryParts
Map loadTextPart(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT ident_nsid, ident_name, mimetype, charcount, linecount, reads, last_read "
+ "FROM us_text WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","bad.loadText.part");
de.setParameter(0,String.valueOf(part));
de.setParameter(1,String.valueOf(msgid));
throw de;
} // end if
// Prepare the return value.
HashMap rc = new HashMap();
rc.put(PARAM_PART,new Integer(part));
rc.put(PARAM_IDENTITY,new PropertyKey(rs.getInt(1),rs.getString(2)));
String s = rs.getString(3);
if (!(rs.wasNull()))
rc.put(PARAM_MIMETYPE,s);
int tmp = rs.getInt(4);
if (!(rs.wasNull()))
rc.put(PARAM_SIZE,new Integer(tmp));
tmp = rs.getInt(5);
if (!(rs.wasNull()))
rc.put(PARAM_LINECOUNT,new Integer(tmp));
rc.put(PARAM_READS,new Integer(rs.getInt(6)));
java.util.Date dt = m_utils.getDateTime(rs,7);
if (!(rs.wasNull()))
rc.put(PARAM_LASTREAD,dt);
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end loadTextPart
Map loadTextPart(long msgid, PropertyKey identity) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT part, mimetype, charcount, linecount, reads, last_read "
+ "FROM us_text WHERE msgid = ? AND ident_nsid = ? AND ident_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,identity.getNamespaceID());
stmt.setString(3,identity.getName());
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","bad.loadText.id");
de.setParameter(0,String.valueOf(identity.getNamespaceID()));
de.setParameter(1,identity.getName());
de.setParameter(2,String.valueOf(msgid));
throw de;
} // end if
// Prepare the return value.
HashMap rc = new HashMap();
rc.put(PARAM_PART,new Integer(rs.getInt(1)));
rc.put(PARAM_IDENTITY,identity);
String s = rs.getString(2);
if (!(rs.wasNull()))
rc.put(PARAM_MIMETYPE,s);
int tmp = rs.getInt(3);
if (!(rs.wasNull()))
rc.put(PARAM_SIZE,new Integer(tmp));
tmp = rs.getInt(4);
if (!(rs.wasNull()))
rc.put(PARAM_LINECOUNT,new Integer(tmp));
rc.put(PARAM_READS,new Integer(rs.getInt(5)));
java.util.Date dt = m_utils.getDateTime(rs,6);
if (!(rs.wasNull()))
rc.put(PARAM_LASTREAD,dt);
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end loadTextPart
Map loadBinaryPart(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT ident_nsid, ident_name, mimetype, datalen, filename, reads, last_read "
+ "FROM us_binary WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","bad.loadBinary.part");
de.setParameter(0,String.valueOf(part));
de.setParameter(1,String.valueOf(msgid));
throw de;
} // end if
// Prepare the return value.
HashMap rc = new HashMap();
rc.put(PARAM_PART,new Integer(part));
rc.put(PARAM_IDENTITY,new PropertyKey(rs.getInt(1),rs.getString(2)));
String s = rs.getString(3);
if (!(rs.wasNull()))
rc.put(PARAM_MIMETYPE,s);
int tmp = rs.getInt(4);
if (!(rs.wasNull()))
rc.put(PARAM_SIZE,new Integer(tmp));
s = rs.getString(5);
if (!(rs.wasNull()))
rc.put(PARAM_FILENAME,s);
rc.put(PARAM_READS,new Integer(rs.getInt(6)));
java.util.Date dt = m_utils.getDateTime(rs,7);
if (!(rs.wasNull()))
rc.put(PARAM_LASTREAD,dt);
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end loadBinaryPart
Map loadBinaryPart(long msgid, PropertyKey identity) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT part, mimetype, datalen, filename, reads, last_read "
+ "FROM us_binary WHERE msgid = ? AND ident_nsid = ? AND ident_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,identity.getNamespaceID());
stmt.setString(3,identity.getName());
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","bad.loadBinary.id");
de.setParameter(0,String.valueOf(identity.getNamespaceID()));
de.setParameter(1,identity.getName());
de.setParameter(2,String.valueOf(msgid));
throw de;
} // end if
// Prepare the return value.
HashMap rc = new HashMap();
rc.put(PARAM_PART,new Integer(rs.getInt(1)));
rc.put(PARAM_IDENTITY,identity);
String s = rs.getString(2);
if (!(rs.wasNull()))
rc.put(PARAM_MIMETYPE,s);
int tmp = rs.getInt(3);
if (!(rs.wasNull()))
rc.put(PARAM_SIZE,new Integer(tmp));
s = rs.getString(4);
if (!(rs.wasNull()))
rc.put(PARAM_FILENAME,s);
rc.put(PARAM_READS,new Integer(rs.getInt(5)));
java.util.Date dt = m_utils.getDateTime(rs,6);
if (!(rs.wasNull()))
rc.put(PARAM_LASTREAD,dt);
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end loadBinaryPart
} // end class MessageOps_mysql

View File

@ -0,0 +1,338 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.io.*;
import java.lang.ref.*;
import java.util.*;
import org.apache.commons.collections.*;
import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class TextPartImpl implements UniStoreTextPart
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private TextPartOps m_ops;
private NamespaceCache m_nscache;
private MessageImpl m_parent;
private int m_part;
private QualifiedNameKey m_identity;
private String m_mimetype;
private int m_size;
private int m_linecount;
private int m_nread;
private java.util.Date m_lastread;
private ReferenceMap m_properties;
private SoftReference m_text = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
TextPartImpl(TextPartOps ops, NamespaceCache nscache, MessageImpl parent, Map params) throws DatabaseException
{
m_ops = ops;
m_nscache = nscache;
m_parent = parent;
m_part = ((Integer)(params.get(MessageOps.PARAM_PART))).intValue();
PropertyKey pk = (PropertyKey)(params.get(MessageOps.PARAM_IDENTITY));
m_identity = new QualifiedNameKey(nscache.namespaceIdToName(pk.getNamespaceID()),pk.getName());
m_mimetype = (String)(params.get(MessageOps.PARAM_MIMETYPE));
Integer tmp = (Integer)(params.get(MessageOps.PARAM_SIZE));
if (tmp!=null)
m_size = tmp.intValue();
tmp = (Integer)(params.get(MessageOps.PARAM_LINECOUNT));
if (tmp!=null)
m_linecount = tmp.intValue();
m_nread = ((Integer)(params.get(MessageOps.PARAM_READS))).intValue();
m_lastread = (java.util.Date)(params.get(MessageOps.PARAM_LASTREAD));
m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectProvider
*--------------------------------------------------------------------------------
*/
/**
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be retrieved.
* @return The object reference specified.
*/
public Object getObject(String namespace, String name)
{
try
{ // convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
Object rc = null;
synchronized (this)
{ // start by looking in the properties map
rc = m_properties.get(key);
if (rc==null)
{ // no use - need to try the database
rc = m_ops.getProperty(m_parent.getMessageID(),m_part,key);
if (rc!=null)
m_properties.put(key,rc);
} // end if
} // end synchronized block
if (rc==null)
throw new NoSuchObjectException(this.toString(),namespace,name);
return rc;
} // end try
catch (DatabaseException e)
{ // translate into our NoSuchObjectException but retain the DatabaseException
throw new NoSuchObjectException(this.toString(),namespace,name,e);
} // end catch
} // end getObject
/*--------------------------------------------------------------------------------
* Implementations from interface SecureObjectStore
*--------------------------------------------------------------------------------
*/
/**
* Sets an object into this <CODE>SecureObjectStore</CODE>.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be set.
* @param value The object to set into the <CODE>SecureObjectStore</CODE>.
* @return The previous object that was set into the <CODE>SecureObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error setting the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* set this object value into this <CODE>SecureObjectStore</CODE>.
*/
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
throws DatabaseException, DynamoSecurityException
{
m_parent.testPermission(caller,namespace,"set.property","no.setProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by setting the database value
rc = m_ops.setProperty(m_parent.getMessageID(),m_part,key,value);
// and cache it, too
m_properties.put(key,value);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end setObject
/**
* Removes an object from this <CODE>SecureObjectStore</CODE>.
*
* @param caller The user performing the operation.
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be removed.
* @return The previous object that was set into the <CODE>SecureObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error removing the object value.
* @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to
* remove this object value from this <CODE>SecureObjectStore</CODE>.
*/
public Object removeObject(DynamoUser caller, String namespace, String name)
throws DatabaseException, DynamoSecurityException
{
m_parent.testPermission(caller,namespace,"remove.property","no.removeProperty");
Object rc = null;
// convert the namespace name to an ID here
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
synchronized (this)
{ // start by killing the database value
rc = m_ops.removeProperty(m_parent.getMessageID(),m_part,key);
// and remove the cached value, too
m_properties.remove(key);
} // end synchronized block
// TODO: m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name));
return rc;
} // end removeObject
/**
* Returns a collection of all object namespaces that have been set into this <CODE>SecureObjectStore</CODE>.
*
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects specifying
* all the object namespaces.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the namespace list.
*/
public Collection getNamespaces() throws DatabaseException
{
// call through to the database to get the list of namespace IDs
int[] ids = m_ops.getPropertyNamespaceIDs(m_parent.getMessageID(),m_part);
ArrayList rc = new ArrayList(ids.length);
for (int i=0; i<ids.length; i++)
rc.add(m_nscache.namespaceIdToName(ids[i]));
return Collections.unmodifiableList(rc);
} // end getNamespaces
/**
* Returns a collection of all object names that have been set into this <CODE>SecureObjectStore</CODE> under
* a given namespace.
*
* @param namespace The namespace to look for names under.
* @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects
* specifying all the object names for this namespace.
* @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the object name list.
*/
public Collection getNamesForNamespace(String namespace) throws DatabaseException
{
// call through to the database to get the data for this namespace
int nsid = m_nscache.namespaceNameToId(namespace);
Map data = m_ops.getAllProperties(m_parent.getMessageID(),m_part,nsid);
// we both create the return value and cache the data values
ArrayList rc = new ArrayList(data.size());
synchronized (this)
{ // do the transfer...
Iterator it = data.entrySet().iterator();
while (it.hasNext())
{ // copy one entry at a time
Map.Entry ntry = (Map.Entry)(it.next());
rc.add(ntry.getKey().toString());
m_properties.put(new PropertyKey(nsid,ntry.getKey().toString()),ntry.getValue());
} // end while
} // end synchronized block
return Collections.unmodifiableList(rc);
} // end getNamesForNamespace
/*--------------------------------------------------------------------------------
* Implementations from interface UniStorePart
*--------------------------------------------------------------------------------
*/
public long getMessageID()
{
return m_parent.getMessageID();
} // end getMessageID
public int getPartIndex()
{
return m_part;
} // end getPartIndex
public QualifiedNameKey getPartIdentity()
{
return m_identity;
} // end getPartIdentity
public String getMimeType()
{
return m_mimetype;
} // end getMimeType
public int getSize()
{
return m_size;
} // end getSize
public int getNumReads()
{
return m_nread;
} // end getNumReads
public java.util.Date getLastReadDate()
{
return m_lastread;
} // end getLastReadDate
public void touchRead() throws DatabaseException
{
synchronized (this)
{ // touch the database, then the local values
java.util.Date tmp = m_ops.touchRead(m_parent.getMessageID(),m_part);
m_nread++;
m_lastread = tmp;
} // end synchronized block
// TODO: post an update?
} // end touchRead
/*--------------------------------------------------------------------------------
* Implementations from interface UniStoreTextPart
*--------------------------------------------------------------------------------
*/
public int getLineCount()
{
return m_linecount;
} // end getLineCount
public synchronized String getText() throws DatabaseException
{
String rc = null;
if (m_text!=null)
rc = (String)(m_text.get());
if (rc==null)
{ // load text fom database and reload to reference
rc = m_ops.getText(m_parent.getMessageID(),m_part);
m_text = new SoftReference(rc);
} // end if
return rc;
} // end getText
public Reader getTextAsReader() throws DatabaseException
{
return new StringReader(this.getText());
} // end getTextAsReader
} // end class TextPartImpl

View File

@ -0,0 +1,58 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.util.*;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
abstract class TextPartOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected TextPartOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
abstract Object getProperty(long msgid, int part, PropertyKey key) throws DatabaseException;
abstract Object setProperty(long msgid, int part, PropertyKey key, Object value) throws DatabaseException;
abstract Object removeProperty(long msgid, int part, PropertyKey key) throws DatabaseException;
abstract int[] getPropertyNamespaceIDs(long msgid, int part) throws DatabaseException;
abstract Map getAllProperties(long msgid, int part, int namespace) throws DatabaseException;
abstract java.util.Date touchRead(long msgid, int part) throws DatabaseException;
abstract String getText(long msgid, int part) throws DatabaseException;
} // end class TextPartOps

View File

@ -0,0 +1,458 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.sql.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class TextPartOps_mysql extends TextPartOps
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private PropertySerializer m_psz; // reference to property serializer
private DBUtilities m_utils;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
TextPartOps_mysql(DBConnectionPool pool)
{
super(pool);
m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class));
m_utils = (DBUtilities)(pool.queryService(DBUtilities.class));
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class OpsBase
*--------------------------------------------------------------------------------
*/
public void dispose()
{
m_psz = null;
m_utils = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract implementations from class TextPartOps
*--------------------------------------------------------------------------------
*/
Object getProperty(long msgid, int part, PropertyKey key) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String rc_str = null;
try
{ // get a connection
conn = getConnection();
// look up the property
stmt = conn.prepareStatement("SELECT prop_value FROM us_text_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (!(rs.next()))
return null; // property not found
rc_str = rs.getString(1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(rc_str);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end getProperty
Object setProperty(long msgid, int part, PropertyKey key, Object value) throws DatabaseException
{
String serialized_value = m_psz.serializeProperty(value);
if (serialized_value==null)
{ // serialization exception - throw it
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages","property.serialize");
de.setParameter(0,key.getName());
throw de;
} // end if
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_text_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_text_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
if (old_value!=null)
{ // prepare the statement to update the existing record
stmt = conn.prepareStatement("UPDATE us_text_prop SET prop_value = ? WHERE msgid = ? AND part = ? "
+ "AND nsid = ? AND prop_name = ?;");
stmt.setString(1,serialized_value);
stmt.setLong(2,msgid);
stmt.setInt(3,part);
stmt.setInt(4,key.getNamespaceID());
stmt.setString(5,key.getName());
} // end if
else
{ // prepare the statement to insert a new record
stmt = conn.prepareStatement("INSERT INTO us_text_prop (msgid, part, nsid, prop_name, prop_value) "
+ "VALUES (?, ?, ?, ?, ?);");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
stmt.setString(5,serialized_value);
} // end else
stmt.executeUpdate(); // execute it!
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
if (old_value==null)
return null; // no previous value
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end setProperty
Object removeProperty(long msgid, int part, PropertyKey key) throws DatabaseException
{
String old_value = null;
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_text_prop WRITE;");
// look to see if the property value is already there
stmt = conn.prepareStatement("SELECT prop_value FROM us_text_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
rs = stmt.executeQuery();
if (rs.next())
old_value = rs.getString(1);
else
return null; // no need to remove anything
SQLUtils.shutdown(rs);
rs = null;
SQLUtils.shutdown(stmt);
// delete the database row
stmt = conn.prepareStatement("DELETE FROM us_text_prop WHERE msgid = ? AND part = ? AND nsid = ? "
+ "AND prop_name = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,key.getNamespaceID());
stmt.setString(4,key.getName());
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
// Deserialize the property value.
Object rc = m_psz.deserializeProperty(old_value);
if (rc!=null)
return rc;
// deserialization exception - throw it
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages","property.deserialize");
de.setParameter(0,key.getName());
throw de;
} // end removeProperty
int[] getPropertyNamespaceIDs(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM us_text_prop WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
rs = stmt.executeQuery();
// read out a list of the namespace IDs
ArrayList tmp = new ArrayList();
while (rs.next())
tmp.add(new Integer(rs.getInt(1)));
// create and return the array
int[] rc = new int[tmp.size()];
for (int i=0; i<tmp.size(); i++)
rc[i] = ((Integer)(tmp.get(i))).intValue();
tmp.clear();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getPropertyNamespaceIDs
Map getAllProperties(long msgid, int part, int namespace) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// execute the query!
stmt = conn.prepareStatement("SELECT prop_name, prop_value FROM us_text_prop WHERE msgid = ? AND part = ? "
+ "AND nsid = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
stmt.setInt(3,namespace);
rs = stmt.executeQuery();
// prepare the return value
HashMap rc = new HashMap();
while (rs.next())
{ // copy data out, deserializing properties as we go
String key = rs.getString(1);
Object value = m_psz.deserializeProperty(rs.getString(2));
if (value==null)
{ // deserialization exception - throw it
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages",
"property.deserialize");
de.setParameter(0,key);
throw de;
} // end if
rc.put(key,value);
} // end while
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getAllProperties
java.util.Date touchRead(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES us_text WRITE;");
// prepare and execute the statement
stmt = conn.prepareStatement("UPDATE us_text SET reads = reads + 1, lastread = ? WHERE msgid = ? AND part = ?;");
java.util.Date rc = new java.util.Date();
m_utils.setDateTime(stmt,1,rc);
stmt.setLong(2,msgid);
stmt.setInt(3,part);
stmt.executeUpdate();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end touchRead
String getText(long msgid, int part) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT data FROM us_text WHERE msgid = ? AND part = ?;");
stmt.setLong(1,msgid);
stmt.setInt(2,part);
rs = stmt.executeQuery();
if (!(rs.next()))
{ // could not find the part
DatabaseException de = new DatabaseException(TextPartOps_mysql.class,"UniStoreMessages","bad.loadText.part");
de.setParameter(0,String.valueOf(part));
de.setParameter(1,String.valueOf(msgid));
throw de;
} // end if
return rs.getString(1);
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getText
} // end class TextPartOps_mysql

View File

@ -0,0 +1,195 @@
/*
* 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.unistore;
import java.util.*;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.db.UserManagement;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.security.SecurityReferenceMonitor;
import com.silverwrist.dynamo.util.*;
public class UniStoreManager implements NamedObject, ComponentInitialize, ComponentShutdown, UniStore
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(UniStoreManager.class);
private static int DEFAULT_MSGCACHE_HARD = 100;
private static int DEFAULT_MSGCACHE_SOFT = 1000;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private String m_name; // name of this object
private NamespaceCache m_ns_cache; // namespace cache object
private ManagerOps m_ops; // database operations object
private SecurityReferenceMonitor m_srm; // security reference monitor
private UserManagement m_users; // user management object
private HardSoftCache m_msgcache; // message cache
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public UniStoreManager()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface NamedObject
*--------------------------------------------------------------------------------
*/
public String getName()
{
return m_name;
} // end getName
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentInitialize
*--------------------------------------------------------------------------------
*/
/**
* Initialize the component.
*
* @param config_root Pointer to the section of the Dynamo XML configuration file that configures this
* particular component. This is to be considered "read-only" by the component.
* @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider}
* which provides initialization services to the component. This will include an implementation
* of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to
* get information about other objects previously initialized by the application.
* @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component
* configuration.
*/
public void initialize(Element config_root, ServiceProvider services) throws ConfigException
{
logger.info("UniStoreManager initializing");
XMLLoader loader = XMLLoader.get();
String conn_name = null;
String nscache_name = null;
String srm_name = null;
String users_name = null;
int msgcache_hard = DEFAULT_MSGCACHE_HARD, msgcache_soft = DEFAULT_MSGCACHE_SOFT;
try
{ // verify the right node name
loader.verifyNodeName(config_root,"object");
// get the object's name
m_name = loader.getAttribute(config_root,"name");
// get the database configuration connection
DOMElementHelper config_root_h = new DOMElementHelper(config_root);
Element elt = loader.getSubElement(config_root_h,"database");
conn_name = loader.getAttribute(elt,"connection");
nscache_name = loader.getAttribute(elt,"namespaces");
// get the security reference monitor name
elt = loader.getSubElement(config_root_h,"security");
srm_name = loader.getAttribute(elt,"object");
// get the user management object name
elt = loader.getSubElement(config_root_h,"user-manager");
users_name = loader.getAttribute(elt,"object");
// get the message cache configuration
elt = config_root_h.getSubElement("message-cache");
if (elt!=null)
{ // load the limits
msgcache_hard = loader.getAttributeInt(elt,"hardlimit",DEFAULT_MSGCACHE_HARD);
msgcache_soft = loader.getAttributeInt(elt,"softlimit",DEFAULT_MSGCACHE_SOFT);
} // end if
} // end try
catch (XMLLoadException e)
{ // error loading XML config data
throw new ConfigException(e);
} // end catch
// Create the message cache.
m_msgcache = new HardSoftCache(msgcache_hard,msgcache_soft);
// Get the database connection pool and namespace cache.
DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name);
m_ns_cache =
(NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name));
// Get the operations object.
m_ops = ManagerOps.get(pool);
// Get the security reference monitor and user manager object..
m_srm = (SecurityReferenceMonitor)(GetObjectUtils.getDynamoComponent(services,SecurityReferenceMonitor.class,
srm_name));
m_users = (UserManagement)(GetObjectUtils.getDynamoComponent(services,UserManagement.class,users_name));
} // end initialize
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentShutdown
*--------------------------------------------------------------------------------
*/
public void shutdown()
{
m_msgcache.clear();
m_srm = null;
m_users = null;
m_ns_cache = null;
m_ops.dispose();
m_ops = null;
} // end shutdown
/*--------------------------------------------------------------------------------
* Implementations from interface UniStore
*--------------------------------------------------------------------------------
*/
public synchronized UniStoreMessage getMessage(long msgid) throws DatabaseException
{
Long key = new Long(msgid);
MessageImpl rc = (MessageImpl)(m_msgcache.get(key));
if (rc==null)
{ // need to look it up in the database!
Map params = m_ops.getMessageData(msgid);
rc = new MessageImpl(m_ops.getMessageOps(),m_ns_cache,m_srm,m_users,params);
params.clear();
m_msgcache.put(key,rc);
} // end if
return rc;
} // end getMessage
} // end class UniStoreManager

View File

@ -0,0 +1,28 @@
# 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) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
#
# Contributor(s):
# ---------------------------------------------------------------------------------
# This file has been localized for the en_US locale
no.message=Unable to find the message with ID #{0} in the Universal Message Store.
property.serialize=The value of property "{0}" could not be serialized.
property.deserialize=The value of property "{0}" could not be deserialized.
no.setProperty=You are not authorized to set properties on message #{0}.
no.removeProperty=You are not authorized to remove properties from message #{0}.
no.setParent=You are not authorized to change the parent message information of message #{0}.
no.setACL=You are not authorized to change the access control list of message #{0}.
bad.loadText.part=Unable to find text part #{0} of message #{1} in the Universal Message Store.
bad.loadText.id=Unable to find text part with ID {0}::{1} in message #{2} in the Universal Message Store.
bad.loadBinary.part=Unable to find binary part #{0} of message #{1} in the Universal Message Store.
bad.loadBinary.id=Unable to find binary part with ID {0}::{1} in message #{2} in the Universal Message Store.