added message part add/delete and message create/delete to the UniStore
operations
This commit is contained in:
parent
5fe6dd78b3
commit
172ec3b314
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import com.silverwrist.dynamo.iface.UniStoreMessage;
|
||||
|
||||
public class MessageCreatedEvent extends MessageUpdateEvent
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public MessageCreatedEvent(UniStoreMessage src)
|
||||
{
|
||||
super(src);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class MessageUpdateEvent
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MessageCreatedEvent: new message ID#" + getMessage().getMessageID();
|
||||
|
||||
} // end toString
|
||||
|
||||
} // end class MessageCreatedEvent
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import com.silverwrist.dynamo.iface.UniStoreMessage;
|
||||
|
||||
public class MessageDeletedEvent extends MessageUpdateEvent
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public MessageDeletedEvent(UniStoreMessage src)
|
||||
{
|
||||
super(src);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class MessageUpdateEvent
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MessageDeletedEvent: deleted message ID#" + getMessage().getMessageID();
|
||||
|
||||
} // end toString
|
||||
|
||||
} // end class MessageDeletedEvent
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import com.silverwrist.dynamo.iface.UniStorePart;
|
||||
|
||||
public class MessagePartAddedEvent extends MessagePartUpdateEvent
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public MessagePartAddedEvent(UniStorePart src)
|
||||
{
|
||||
super(src);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class MessagePartUpdateEvent
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MessagePartAddedEvent: message ID#" + getMessagePart().getMessageID() + ", new "
|
||||
+ (isBinaryPart() ? "binary" : "text") + " part " + getMessagePart().getPartIdentity();
|
||||
|
||||
} // end toString
|
||||
|
||||
} // end class MessagePartAddedEvent
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.event;
|
||||
|
||||
import com.silverwrist.dynamo.iface.UniStorePart;
|
||||
|
||||
public class MessagePartDeletedEvent extends MessagePartUpdateEvent
|
||||
{
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public MessagePartDeletedEvent(UniStorePart src)
|
||||
{
|
||||
super(src);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class MessagePartUpdateEvent
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MessagePartDeletedEvent: message ID#" + getMessagePart().getMessageID() + ", deleted "
|
||||
+ (isBinaryPart() ? "binary" : "text") + " part " + getMessagePart().getPartIdentity();
|
||||
|
||||
} // end toString
|
||||
|
||||
} // end class MessagePartDeletedEvent
|
|
@ -109,16 +109,16 @@ class RewriteURLs implements HTMLCheckerConfigurator, HTMLRewriter
|
|||
try
|
||||
{ // pre-compile all our regex patterns
|
||||
// recognize: http://<host>[:<port>]...
|
||||
l.add(new Match("^http://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?"));
|
||||
l.add(new Match("^http://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?$"));
|
||||
|
||||
// recognize: ftp://<host>[:<port>]...
|
||||
l.add(new Match("^ftp://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?"));
|
||||
l.add(new Match("^ftp://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?$"));
|
||||
|
||||
// recognize: gopher://<host>[:<port>]...
|
||||
l.add(new Match("^gopher://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?"));
|
||||
l.add(new Match("^gopher://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?(/.*)?$"));
|
||||
|
||||
// recognize: mailto:<valid E-mail address>
|
||||
l.add(new Match("^mailto:[A-Za-z0-9!#$%*+-/=?^_`{|}~.]+@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*"));
|
||||
// recognize: mailto:<valid E-mail address>[?queryinfo]
|
||||
l.add(new Match("^mailto:[A-Za-z0-9!#$%*+-/=?^_`{|}~.]+@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\?.+)?$"));
|
||||
|
||||
// recognize: news:<newsgroup name>
|
||||
l.add(new Match("^news:[A-Za-z0-9-_]+(\\.[A-Za-z0-9-_]+)*$"));
|
||||
|
@ -137,13 +137,13 @@ class RewriteURLs implements HTMLCheckerConfigurator, HTMLRewriter
|
|||
l.add(new Match("^tn3270://[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]+)?$"));
|
||||
|
||||
// recognize "www.whatever" and tack http:// onto the front
|
||||
l.add(new Match("^www\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?","http://"));
|
||||
l.add(new Match("^www\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?$","http://"));
|
||||
|
||||
// recognize "ftp.whatever" and tack ftp:// onto the front
|
||||
l.add(new Match("^ftp\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?","ftp://"));
|
||||
l.add(new Match("^ftp\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?$","ftp://"));
|
||||
|
||||
// recognize "gopher.whatever" and tack gopher:// onto the front
|
||||
l.add(new Match("^gopher\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?","gopher://"));
|
||||
l.add(new Match("^gopher\\.[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(/.*)?$","gopher://"));
|
||||
|
||||
} // end try
|
||||
catch (PatternSyntaxException pe)
|
||||
|
|
|
@ -23,4 +23,6 @@ public interface UniStore
|
|||
{
|
||||
public UniStoreMessage getMessage(long msgid) throws DatabaseException;
|
||||
|
||||
public UniStoreMessage createMessage(DynamoUser caller) throws DatabaseException;
|
||||
|
||||
} // end interface UniStore
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
package com.silverwrist.dynamo.iface;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.acl.AclNotFoundException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -61,4 +63,19 @@ public interface UniStoreMessage extends SecureObjectStore
|
|||
|
||||
public List getBinaryParts() throws DatabaseException;
|
||||
|
||||
public UniStoreTextPart createTextPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
HTMLChecker data) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
public UniStoreTextPart createTextPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
String data) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
public UniStoreBinaryPart createBinaryPart(DynamoUser caller, String namespace, String name, DataItem data)
|
||||
throws IOException, DatabaseException, DynamoSecurityException;
|
||||
|
||||
public UniStoreBinaryPart createBinaryPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
String filename, int length, InputStream data)
|
||||
throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
public void delete(DynamoUser caller) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
} // end interface UniStoreMessage
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.silverwrist.dynamo.iface;
|
|||
|
||||
import java.util.Date;
|
||||
import com.silverwrist.dynamo.except.DatabaseException;
|
||||
import com.silverwrist.dynamo.except.DynamoSecurityException;
|
||||
import com.silverwrist.dynamo.util.QualifiedNameKey;
|
||||
|
||||
public interface UniStorePart extends SecureObjectStore
|
||||
|
@ -41,4 +42,6 @@ public interface UniStorePart extends SecureObjectStore
|
|||
|
||||
public void touchRead() throws DatabaseException;
|
||||
|
||||
public void delete(DynamoUser caller) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
} // end interface UniStorePart
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.sql.Blob;
|
|||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import org.apache.commons.collections.*;
|
||||
import com.silverwrist.dynamo.Namespaces;
|
||||
import com.silverwrist.dynamo.db.NamespaceCache;
|
||||
import com.silverwrist.dynamo.event.*;
|
||||
import com.silverwrist.dynamo.except.*;
|
||||
|
@ -141,7 +142,7 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
private ReferenceMap m_properties;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
* Constructors
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -166,6 +167,36 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
} // end constructor
|
||||
|
||||
BinaryPartImpl(PostDynamicUpdate post, MessageImpl parent, int part, QualifiedNameKey identity)
|
||||
{
|
||||
m_ops = null;
|
||||
m_nscache = null;
|
||||
m_post = post;
|
||||
m_parent = parent;
|
||||
m_part = part;
|
||||
m_identity = identity;
|
||||
m_mimetype = null;
|
||||
m_size = -1;
|
||||
m_filename = null;
|
||||
m_nread = 0;
|
||||
m_lastread = null;
|
||||
m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class Object
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (m_ops==null)
|
||||
return "(deleted binary part)";
|
||||
return "message " + m_parent.getMessageID() + ", binary part " + m_identity.toString();
|
||||
|
||||
} // end toString
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface ObjectProvider
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -180,6 +211,8 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
*/
|
||||
public Object getObject(String namespace, String name)
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new NoSuchObjectException(this.toString(),namespace,name);
|
||||
try
|
||||
{ // convert the namespace name to an ID here
|
||||
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
|
||||
|
@ -231,6 +264,8 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,namespace,"set.property","no.setProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -264,6 +299,8 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
public Object removeObject(DynamoUser caller, String namespace, String name)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,namespace,"remove.property","no.removeProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -291,6 +328,9 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
*/
|
||||
public Collection getNamespaces() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// call through to the database to get the list of namespace IDs
|
||||
int[] ids = m_ops.getPropertyNamespaceIDs(m_parent.getMessageID(),m_part);
|
||||
|
||||
|
@ -312,6 +352,9 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
*/
|
||||
public Collection getNamesForNamespace(String namespace) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// 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);
|
||||
|
@ -342,7 +385,7 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
public long getMessageID()
|
||||
{
|
||||
return m_parent.getMessageID();
|
||||
return (m_parent==null) ? -1L : m_parent.getMessageID();
|
||||
|
||||
} // end getMessageID
|
||||
|
||||
|
@ -390,6 +433,8 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
public void touchRead() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
synchronized (this)
|
||||
{ // touch the database, then the local values
|
||||
java.util.Date tmp = m_ops.touchRead(m_parent.getMessageID(),m_part);
|
||||
|
@ -402,6 +447,22 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
} // end touchRead
|
||||
|
||||
public synchronized void delete(DynamoUser caller) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"delete.part","no.deletePart");
|
||||
|
||||
// Cut this object loose from the parent.
|
||||
m_parent.deletedBinaryPart(m_part,m_identity);
|
||||
|
||||
// Zap it from the database.
|
||||
m_ops.delete(m_parent.getMessageID(),m_part);
|
||||
|
||||
baleeted(); // BALEETED!
|
||||
|
||||
} // end delete
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface DataItem
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -415,6 +476,14 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
public InputStream getDataStream() throws IOException
|
||||
{
|
||||
if (m_ops==null)
|
||||
{ // we've been deleted!
|
||||
IOException ioe = new IOException("Part has been deleted");
|
||||
ioe.initCause(new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted"));
|
||||
throw ioe;
|
||||
|
||||
} // end if
|
||||
|
||||
try
|
||||
{ // call through to the database to get the data stream
|
||||
return m_ops.getData(m_parent.getMessageID(),m_part);
|
||||
|
@ -432,6 +501,14 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
|
||||
public Blob getBlob() throws SQLException
|
||||
{
|
||||
if (m_ops==null)
|
||||
{ // we've been deleted!
|
||||
SQLException se = new SQLException("Part has been deleted");
|
||||
se.initCause(new DatabaseException(BinaryPartImpl.class,"UniStoreMessages","part.deleted"));
|
||||
throw se;
|
||||
|
||||
} // end if
|
||||
|
||||
try
|
||||
{ // load the data from the database and create the Blob around it
|
||||
byte[] data = new byte[m_size];
|
||||
|
@ -461,4 +538,43 @@ class BinaryPartImpl implements UniStoreBinaryPart
|
|||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void resetPartNumber(int new_num)
|
||||
{
|
||||
m_part = new_num;
|
||||
|
||||
} // end resetPartNumber
|
||||
|
||||
/**
|
||||
* Called after the part has been deleted, either alone or through the entire message being deleted. This
|
||||
* method nulls out the internal data of the object and posts a "part-deleted" notification.<P>
|
||||
* See <A HREF="http://www.homestarrunner.com/sbemail50.html">this page</A> for the source of the method name.
|
||||
*/
|
||||
synchronized void baleeted()
|
||||
{
|
||||
// Cut loose most of our data before we post an update event.
|
||||
m_ops = null;
|
||||
m_nscache = null;
|
||||
m_mimetype = null;
|
||||
m_size = -1;
|
||||
m_filename = null;
|
||||
m_nread = 0;
|
||||
m_lastread = null;
|
||||
m_properties.clear();
|
||||
|
||||
// Post the "deleted" notification event.
|
||||
m_post.postUpdate(new MessagePartDeletedEvent(this));
|
||||
|
||||
// Cut loose the rest of our data.
|
||||
m_post = null;
|
||||
m_parent = null;
|
||||
m_part = -1;
|
||||
m_identity = null;
|
||||
|
||||
} // end baleeted
|
||||
|
||||
} // end class BinaryPartImpl
|
||||
|
|
|
@ -59,4 +59,6 @@ abstract class BinaryPartOps extends OpsBase
|
|||
|
||||
abstract int getData(long msgid, int part, byte[] here) throws IOException, DatabaseException;
|
||||
|
||||
abstract void delete(long msgid, int part) throws DatabaseException;
|
||||
|
||||
} // end class BinaryPartOps
|
||||
|
|
|
@ -503,4 +503,57 @@ class BinaryPartOps_mysql extends BinaryPartOps
|
|||
|
||||
} // end getData
|
||||
|
||||
void delete(long msgid, int part) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
Statement stmt2 = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// lock the tables
|
||||
stmt2 = conn.createStatement();
|
||||
stmt2.executeUpdate("LOCK TABLES us_binary WRITE, us_binary_props WRITE;");
|
||||
|
||||
// delete all entries from the main and property tables
|
||||
stmt = conn.prepareStatement("DELETE FROM us_binary WHERE msgid = ? AND part = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_binary_prop WHERE msgid = ? AND part = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
|
||||
// renumber all entries above that one to close the gap
|
||||
stmt = conn.prepareStatement("UPDATE us_binary SET part = part - 1 WHERE msgid = ? AND part > ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("UPDATE us_binary_prop SET part = part - 1 WHERE msgid = ? AND part > ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
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(stmt);
|
||||
SQLUtils.shutdown(stmt2);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end delete
|
||||
|
||||
} // end class BinaryPartOps_mysql
|
||||
|
|
|
@ -77,6 +77,8 @@ abstract class ManagerOps extends OpsBase
|
|||
|
||||
abstract Map getMessageData(long msgid) throws DatabaseException;
|
||||
|
||||
abstract long createMessage(int creator, java.util.Date postdate) throws DatabaseException;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
|
|
|
@ -116,4 +116,43 @@ public class ManagerOps_mysql extends ManagerOps
|
|||
|
||||
} // end getMessageData
|
||||
|
||||
long createMessage(int creator, java.util.Date postdate) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
Statement stmt2 = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// lock the base table
|
||||
stmt2 = conn.createStatement();
|
||||
stmt2.executeUpdate("LOCK TABLES us_head WRITE;");
|
||||
|
||||
// create and execute the INSERT statement
|
||||
stmt = conn.prepareStatement("INSERT INTO us_head (creator, posted) VALUES (?, ?);");
|
||||
stmt.setInt(1,creator);
|
||||
m_utils.setDateTime(stmt,2,postdate);
|
||||
stmt.executeUpdate();
|
||||
|
||||
// return the new message ID
|
||||
return MySQLUtils.getLastInsertLong(conn);
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // translate to a general DatabaseException
|
||||
throw generalException(e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // shut everything down
|
||||
MySQLUtils.unlockTables(conn);
|
||||
SQLUtils.shutdown(stmt);
|
||||
SQLUtils.shutdown(stmt2);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end createMessage
|
||||
|
||||
} // end class ManagerOps_mysql
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
*/
|
||||
package com.silverwrist.dynamo.unistore;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.acl.AclNotFoundException;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import org.apache.commons.collections.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import com.silverwrist.dynamo.Namespaces;
|
||||
|
@ -39,6 +41,10 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
private static Logger logger = Logger.getLogger(MessageImpl.class);
|
||||
|
||||
private static final Integer NO_READS = new Integer(0);
|
||||
|
||||
private static Pattern NEWLINES;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Attributes
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -92,13 +98,109 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private static final int getLineCount(String s)
|
||||
{
|
||||
Matcher m = NEWLINES.matcher(s);
|
||||
int rc = 1;
|
||||
while (m.find())
|
||||
rc++;
|
||||
return rc;
|
||||
|
||||
} // end getLineCount
|
||||
|
||||
private final UniStoreTextPart createTextPart(int nsid, String name, String mimetype, int charcount, int linecount,
|
||||
String text) throws DatabaseException
|
||||
{
|
||||
// Call down to the database to create the part.
|
||||
int partnum = m_ops.createTextPart(m_id,nsid,name,mimetype,charcount,linecount,text);
|
||||
|
||||
// Fake up a parameter buffer to create the part object.
|
||||
Integer key1 = new Integer(partnum);
|
||||
PropertyKey key2 = new PropertyKey(nsid,name);
|
||||
HashMap params = new HashMap();
|
||||
params.put(MessageOps.PARAM_PART,key1);
|
||||
params.put(MessageOps.PARAM_IDENTITY,key2);
|
||||
if (mimetype!=null)
|
||||
params.put(MessageOps.PARAM_MIMETYPE,mimetype);
|
||||
params.put(MessageOps.PARAM_SIZE,new Integer(charcount));
|
||||
params.put(MessageOps.PARAM_LINECOUNT,new Integer(linecount));
|
||||
params.put(MessageOps.PARAM_READS,NO_READS);
|
||||
TextPartImpl rc = new TextPartImpl(m_ops.getTextPartOps(),m_nscache,m_post,this,params);
|
||||
rc.precacheText(text);
|
||||
|
||||
synchronized (this)
|
||||
{ // Add the text part to the internal caches.
|
||||
m_part_to_text.put(key1,rc);
|
||||
m_pk_to_text.put(key2,rc);
|
||||
if (m_text_count>=0)
|
||||
m_text_count++;
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
m_post.postUpdate(new MessagePartAddedEvent(rc));
|
||||
return rc;
|
||||
|
||||
} // end createTextPart
|
||||
|
||||
private final UniStoreBinaryPart createBinaryPart(int nsid, String name, String mimetype, String filename,
|
||||
int length, InputStream data) throws DatabaseException
|
||||
{
|
||||
// Call down to the database to create the part.
|
||||
int partnum = m_ops.createBinaryPart(m_id,nsid,name,mimetype,filename,length,data);
|
||||
|
||||
// Fake up a parameter buffer to create the part object.
|
||||
Integer key1 = new Integer(partnum);
|
||||
PropertyKey key2 = new PropertyKey(nsid,name);
|
||||
HashMap params = new HashMap();
|
||||
params.put(MessageOps.PARAM_PART,key1);
|
||||
params.put(MessageOps.PARAM_IDENTITY,key2);
|
||||
if (mimetype!=null)
|
||||
params.put(MessageOps.PARAM_MIMETYPE,mimetype);
|
||||
params.put(MessageOps.PARAM_SIZE,new Integer(length));
|
||||
if (filename!=null)
|
||||
params.put(MessageOps.PARAM_FILENAME,filename);
|
||||
params.put(MessageOps.PARAM_READS,NO_READS);
|
||||
BinaryPartImpl rc = new BinaryPartImpl(m_ops.getBinaryPartOps(),m_nscache,m_post,this,params);
|
||||
|
||||
synchronized (this)
|
||||
{ // Add the binary part to the internal caches.
|
||||
m_part_to_binary.put(key1,rc);
|
||||
m_pk_to_binary.put(key2,rc);
|
||||
if (m_binary_count>=0)
|
||||
m_binary_count++;
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
m_post.postUpdate(new MessagePartAddedEvent(rc));
|
||||
return rc;
|
||||
|
||||
} // end createBinaryPart
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class Object
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (m_ops==null)
|
||||
return "(deleted message)";
|
||||
return "message " + m_id;
|
||||
|
||||
} // end toString
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface ObjectProvider
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
|
||||
* Retrieves an object from this message's properties.
|
||||
*
|
||||
* @param namespace The namespace to interpret the name relative to.
|
||||
* @param name The name of the object to be retrieved.
|
||||
|
@ -106,6 +208,9 @@ class MessageImpl implements UniStoreMessage
|
|||
*/
|
||||
public Object getObject(String namespace, String name)
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new NoSuchObjectException(this.toString(),namespace,name);
|
||||
|
||||
try
|
||||
{ // convert the namespace name to an ID here
|
||||
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
|
||||
|
@ -157,6 +262,8 @@ class MessageImpl implements UniStoreMessage
|
|||
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
testPermission(caller,namespace,"set.property","no.setProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -190,6 +297,8 @@ class MessageImpl implements UniStoreMessage
|
|||
public Object removeObject(DynamoUser caller, String namespace, String name)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
testPermission(caller,namespace,"remove.property","no.removeProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -217,6 +326,9 @@ class MessageImpl implements UniStoreMessage
|
|||
*/
|
||||
public Collection getNamespaces() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// call through to the database to get the list of namespace IDs
|
||||
int[] ids = m_ops.getPropertyNamespaceIDs(m_id);
|
||||
|
||||
|
@ -238,6 +350,9 @@ class MessageImpl implements UniStoreMessage
|
|||
*/
|
||||
public Collection getNamesForNamespace(String namespace) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// 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);
|
||||
|
@ -320,7 +435,9 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public DynamoUser getCreator() throws DatabaseException
|
||||
{
|
||||
return m_users.getUser(m_creator);
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
return (m_users==null) ? null : m_users.getUser(m_creator);
|
||||
|
||||
} // end getCreator
|
||||
|
||||
|
@ -332,7 +449,12 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public DynamoAcl getAcl() throws DatabaseException, AclNotFoundException
|
||||
{
|
||||
return m_srm.getAcl(m_aclid);
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
if ((m_aclid<0) || (m_srm==null))
|
||||
return null;
|
||||
else
|
||||
return m_srm.getAcl(m_aclid);
|
||||
|
||||
} // end getAcl
|
||||
|
||||
|
@ -355,6 +477,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public synchronized int getNumTextParts() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
if (m_text_count<0)
|
||||
m_text_count = m_ops.getNumTextParts(m_id);
|
||||
return m_text_count;
|
||||
|
@ -363,6 +487,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public synchronized int getNumBinaryParts() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
if (m_binary_count<0)
|
||||
m_binary_count = m_ops.getNumBinaryParts(m_id);
|
||||
return m_binary_count;
|
||||
|
@ -371,6 +497,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public UniStoreTextPart getTextPart(int index) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
Integer key = new Integer(index);
|
||||
TextPartImpl rc = null;
|
||||
synchronized (this)
|
||||
|
@ -408,6 +536,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public UniStoreTextPart getTextPart(String namespace, String name) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
|
||||
TextPartImpl rc = null;
|
||||
synchronized (this)
|
||||
|
@ -440,6 +570,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public UniStoreBinaryPart getBinaryPart(int index) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
Integer key = new Integer(index);
|
||||
BinaryPartImpl rc = null;
|
||||
synchronized (this)
|
||||
|
@ -477,6 +609,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public UniStoreBinaryPart getBinaryPart(String namespace, String name) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
|
||||
BinaryPartImpl rc = null;
|
||||
synchronized (this)
|
||||
|
@ -509,6 +643,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public List getTextParts() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
int n = this.getNumTextParts();
|
||||
ArrayList rc = new ArrayList(n);
|
||||
for (int i=1; i<=n; i++)
|
||||
|
@ -519,6 +655,8 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
public List getBinaryParts() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
int n = this.getNumBinaryParts();
|
||||
ArrayList rc = new ArrayList(n);
|
||||
for (int i=1; i<=n; i++)
|
||||
|
@ -527,6 +665,140 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
} // end getBinaryParts
|
||||
|
||||
public UniStoreTextPart createTextPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
HTMLChecker data) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"create.textPart","no.createPart");
|
||||
return createTextPart(m_nscache.namespaceNameToId(namespace),name,mimetype,data.getLength(),data.getLines(),
|
||||
data.getValue());
|
||||
|
||||
} // end createTextPart
|
||||
|
||||
public UniStoreTextPart createTextPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
String data) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"create.textPart","no.createPart");
|
||||
return createTextPart(m_nscache.namespaceNameToId(namespace),name,mimetype,data.length(),getLineCount(data),data);
|
||||
|
||||
} // end createTextPart
|
||||
|
||||
public UniStoreBinaryPart createBinaryPart(DynamoUser caller, String namespace, String name, DataItem data)
|
||||
throws IOException, DatabaseException, DynamoSecurityException
|
||||
{
|
||||
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"create.binaryPart","no.createPart");
|
||||
return createBinaryPart(m_nscache.namespaceNameToId(namespace),name,data.getMimeType(),data.getName(),
|
||||
data.getSize(),data.getDataStream());
|
||||
|
||||
} // end createBinaryPart
|
||||
|
||||
public UniStoreBinaryPart createBinaryPart(DynamoUser caller, String namespace, String name, String mimetype,
|
||||
String filename, int length, InputStream data)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"create.binaryPart","no.createPart");
|
||||
return createBinaryPart(m_nscache.namespaceNameToId(namespace),name,mimetype,filename,length,data);
|
||||
|
||||
} // end createBinaryPart
|
||||
|
||||
public synchronized void delete(DynamoUser caller) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"delete.message","no.deleteMessage");
|
||||
|
||||
// We need to have lists of the text and binary parts on hand before we delete everything, so that we can
|
||||
// send out notifications. However, not every one of the parts will be in our cache, so we'll need to create
|
||||
// some temporary instances, but use the cached ones whereever feasible.
|
||||
Map pmap = m_ops.listTextParts(m_id);
|
||||
ArrayList text_parts = new ArrayList(pmap.size());
|
||||
Iterator it = pmap.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // look for a matching TextPartImpl
|
||||
Map.Entry ntry = (Map.Entry)(it.next());
|
||||
TextPartImpl p = (TextPartImpl)(m_part_to_text.get(ntry.getKey()));
|
||||
if (p==null)
|
||||
p = (TextPartImpl)(m_pk_to_text.get(ntry.getValue()));
|
||||
if (p==null)
|
||||
{ // create a "scratch" instance
|
||||
PropertyKey pk = (PropertyKey)(ntry.getValue());
|
||||
QualifiedNameKey qname = new QualifiedNameKey(m_nscache.namespaceIdToName(pk.getNamespaceID()),pk.getName());
|
||||
p = new TextPartImpl(m_post,this,((Integer)(ntry.getKey())).intValue(),qname);
|
||||
|
||||
} // end if
|
||||
|
||||
text_parts.add(p);
|
||||
|
||||
} // end while
|
||||
|
||||
pmap = m_ops.listBinaryParts(m_id);
|
||||
ArrayList binary_parts = new ArrayList(pmap.size());
|
||||
it = pmap.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // look for a matching BinaryPartImpl
|
||||
Map.Entry ntry = (Map.Entry)(it.next());
|
||||
BinaryPartImpl p = (BinaryPartImpl)(m_part_to_binary.get(ntry.getKey()));
|
||||
if (p==null)
|
||||
p = (BinaryPartImpl)(m_pk_to_binary.get(ntry.getValue()));
|
||||
if (p==null)
|
||||
{ // create a "scratch" instance
|
||||
PropertyKey pk = (PropertyKey)(ntry.getValue());
|
||||
QualifiedNameKey qname = new QualifiedNameKey(m_nscache.namespaceIdToName(pk.getNamespaceID()),pk.getName());
|
||||
p = new BinaryPartImpl(m_post,this,((Integer)(ntry.getKey())).intValue(),qname);
|
||||
|
||||
} // end if
|
||||
|
||||
binary_parts.add(p);
|
||||
|
||||
} // end while
|
||||
|
||||
// Delete the message from the database.
|
||||
m_ops.delete(m_id);
|
||||
|
||||
// Cut loose most of our data before we start notifying.
|
||||
m_ops = null;
|
||||
m_nscache = null;
|
||||
m_srm = null;
|
||||
m_users = null;
|
||||
m_parentid = -1;
|
||||
m_seq = -1;
|
||||
m_creator = -1;
|
||||
m_posted = null;
|
||||
m_aclid = -1;
|
||||
m_properties.clear();
|
||||
m_text_count = -1;
|
||||
m_binary_count = -1;
|
||||
m_part_to_text.clear();
|
||||
m_pk_to_text.clear();
|
||||
m_part_to_binary.clear();
|
||||
m_pk_to_binary.clear();
|
||||
|
||||
// Send out the deletion notifications (and clear the data) for all parts.
|
||||
it = text_parts.iterator();
|
||||
while (it.hasNext())
|
||||
{ // make sure all of these parts are BALEETED!
|
||||
TextPartImpl p = (TextPartImpl)(it.next());
|
||||
p.baleeted();
|
||||
|
||||
} // end while
|
||||
|
||||
text_parts.clear();
|
||||
it = binary_parts.iterator();
|
||||
while (it.hasNext())
|
||||
{ // make sure all of these parts are BALEETED!
|
||||
BinaryPartImpl p = (BinaryPartImpl)(it.next());
|
||||
p.baleeted();
|
||||
|
||||
} // end while
|
||||
|
||||
binary_parts.clear();
|
||||
|
||||
// Send our own "BALEETED!" notification.
|
||||
m_post.postUpdate(new MessageDeletedEvent(this));
|
||||
|
||||
// Now cut loose the rest of our data.
|
||||
m_post = null;
|
||||
m_id = -1;
|
||||
|
||||
} // end delete
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -535,6 +807,8 @@ class MessageImpl implements UniStoreMessage
|
|||
void testPermission(DynamoUser caller, String perm_namespace, String perm_name, String fail_message)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(MessageImpl.class,"UniStoreMessages","message.deleted");
|
||||
if (caller.equals(m_srm.getAdminUser()))
|
||||
return; // Administrator can do anything
|
||||
if (m_aclid==-1)
|
||||
|
@ -568,4 +842,127 @@ class MessageImpl implements UniStoreMessage
|
|||
|
||||
} // end testPermission
|
||||
|
||||
void zeroCounts()
|
||||
{
|
||||
m_text_count = 0;
|
||||
m_binary_count = 0;
|
||||
|
||||
} // end zeroCounts
|
||||
|
||||
void deletedTextPart(int partnum, QualifiedNameKey identity) throws DatabaseException
|
||||
{
|
||||
PropertyKey pk = new PropertyKey(m_nscache.namespaceNameToId(identity.getNamespace()),identity.getName());
|
||||
synchronized (this)
|
||||
{ // Remove the entry from the cache reference maps.
|
||||
m_part_to_text.remove(new Integer(partnum));
|
||||
m_pk_to_text.remove(pk);
|
||||
if (m_text_count>=0)
|
||||
m_text_count--;
|
||||
|
||||
// All entries with a part number higher than the deleted part number have to be renumbered downwards.
|
||||
// First, scan through the keyset to find all the appropriate part numbers, get their values, and lock them
|
||||
// into a hard HashMap to keep them in memory while we do this.
|
||||
HashMap temp = new HashMap();
|
||||
Iterator it = m_part_to_text.keySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // get each key in turn and check it
|
||||
Integer key = (Integer)(it.next());
|
||||
if (key.intValue()>partnum)
|
||||
{ // now see if the object's in memory
|
||||
TextPartImpl obj = (TextPartImpl)(m_part_to_text.get(key));
|
||||
if (obj!=null)
|
||||
temp.put(key,obj);
|
||||
|
||||
} // end if
|
||||
|
||||
} // end while
|
||||
|
||||
// Now go through, poke new part numbers into each of these parts, and get them into the parts
|
||||
// mapping correctly.
|
||||
it = temp.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // get each part in turn and deal with it
|
||||
Map.Entry ntry = (Map.Entry)(it.next());
|
||||
m_part_to_text.remove(ntry.getKey());
|
||||
int new_partnum = ((Integer)(ntry.getKey())).intValue() - 1;
|
||||
TextPartImpl obj = (TextPartImpl)(ntry.getValue());
|
||||
obj.resetPartNumber(new_partnum);
|
||||
m_part_to_text.put(new Integer(new_partnum),obj);
|
||||
|
||||
} // end while
|
||||
|
||||
temp.clear(); // release the extra references
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
} // end deletedTextPart
|
||||
|
||||
void deletedBinaryPart(int partnum, QualifiedNameKey identity) throws DatabaseException
|
||||
{
|
||||
PropertyKey pk = new PropertyKey(m_nscache.namespaceNameToId(identity.getNamespace()),identity.getName());
|
||||
synchronized (this)
|
||||
{ // Remove the entry from the cache reference maps.
|
||||
m_part_to_binary.remove(new Integer(partnum));
|
||||
m_pk_to_binary.remove(pk);
|
||||
if (m_binary_count>=0)
|
||||
m_binary_count--;
|
||||
|
||||
// All entries with a part number higher than the deleted part number have to be renumbered downwards.
|
||||
// First, scan through the keyset to find all the appropriate part numbers, get their values, and lock them
|
||||
// into a hard HashMap to keep them in memory while we do this.
|
||||
HashMap temp = new HashMap();
|
||||
Iterator it = m_part_to_binary.keySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // get each key in turn and check it
|
||||
Integer key = (Integer)(it.next());
|
||||
if (key.intValue()>partnum)
|
||||
{ // now see if the object's in memory
|
||||
BinaryPartImpl obj = (BinaryPartImpl)(m_part_to_binary.get(key));
|
||||
if (obj!=null)
|
||||
temp.put(key,obj);
|
||||
|
||||
} // end if
|
||||
|
||||
} // end while
|
||||
|
||||
// Now go through, poke new part numbers into each of these parts, and get them into the parts
|
||||
// mapping correctly.
|
||||
it = temp.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{ // get each part in turn and deal with it
|
||||
Map.Entry ntry = (Map.Entry)(it.next());
|
||||
m_part_to_binary.remove(ntry.getKey());
|
||||
int new_partnum = ((Integer)(ntry.getKey())).intValue() - 1;
|
||||
BinaryPartImpl obj = (BinaryPartImpl)(ntry.getValue());
|
||||
obj.resetPartNumber(new_partnum);
|
||||
m_part_to_binary.put(new Integer(new_partnum),obj);
|
||||
|
||||
} // end while
|
||||
|
||||
temp.clear(); // release the extra references
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
} // end deletedBinaryPart
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Static initializer
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{ // set up our patterns
|
||||
NEWLINES = Pattern.compile("\\r?\\n?"); // matches CR, LF, or CRLF
|
||||
|
||||
} // end try
|
||||
catch (PatternSyntaxException e)
|
||||
{ // just log the error
|
||||
logger.fatal("Pattern compile error in MessageImpl",e);
|
||||
|
||||
} // end catch
|
||||
|
||||
} // end static initializer
|
||||
|
||||
} // end class MessageImpl
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package com.silverwrist.dynamo.unistore;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import com.silverwrist.dynamo.db.OpsBase;
|
||||
import com.silverwrist.dynamo.except.*;
|
||||
|
@ -112,6 +113,18 @@ abstract class MessageOps extends OpsBase
|
|||
|
||||
abstract Map loadBinaryPart(long msgid, PropertyKey identity) throws DatabaseException;
|
||||
|
||||
abstract int createTextPart(long msgid, int nsid, String name, String mimetype, int charcount, int linecount,
|
||||
String data) throws DatabaseException;
|
||||
|
||||
abstract int createBinaryPart(long msgid, int nsid, String name, String mimetype, String filename, int length,
|
||||
InputStream data) throws DatabaseException;
|
||||
|
||||
abstract void delete(long msgid) throws DatabaseException;
|
||||
|
||||
abstract Map listTextParts(long msgid) throws DatabaseException;
|
||||
|
||||
abstract Map listBinaryParts(long msgid) throws DatabaseException;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package com.silverwrist.dynamo.unistore;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import com.silverwrist.util.*;
|
||||
|
@ -790,4 +791,286 @@ class MessageOps_mysql extends MessageOps
|
|||
|
||||
} // end loadBinaryPart
|
||||
|
||||
int createTextPart(long msgid, int nsid, String name, String mimetype, int charcount, int linecount, String data)
|
||||
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;");
|
||||
|
||||
// start by seeing if the identity already exists
|
||||
stmt = conn.prepareStatement("SELECT part FROM us_text WHERE msgid = ? AND ident_nsid = ? AND ident_name = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,nsid);
|
||||
stmt.setString(3,name);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
{ // identity already exists, throw exception
|
||||
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","part.exists");
|
||||
de.setParameter(0,String.valueOf(msgid));
|
||||
throw de;
|
||||
|
||||
} // end if
|
||||
|
||||
SQLUtils.shutdown(rs);
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// get the part number for this part
|
||||
stmt = conn.prepareStatement("SELECT IFNULL(MAX(part),0) FROM us_text WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
rs = stmt.executeQuery();
|
||||
int partnum = SQLUtils.getReturnCountInt(rs,1) + 1;
|
||||
|
||||
SQLUtils.shutdown(rs);
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// perform the insert!
|
||||
stmt = conn.prepareStatement("INSERT INTO us_text (msgid, part, ident_nsid, ident_name, mimetype, charcount, "
|
||||
+ "linecount, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,partnum);
|
||||
stmt.setInt(3,nsid);
|
||||
stmt.setString(4,name);
|
||||
stmt.setString(5,mimetype);
|
||||
stmt.setInt(6,charcount);
|
||||
stmt.setInt(7,linecount);
|
||||
stmt.setString(8,data);
|
||||
stmt.executeUpdate();
|
||||
|
||||
return partnum;
|
||||
|
||||
} // 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 createTextPart
|
||||
|
||||
int createBinaryPart(long msgid, int nsid, String name, String mimetype, String filename, int length,
|
||||
InputStream data) 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;");
|
||||
|
||||
// start by seeing if the identity already exists
|
||||
stmt = conn.prepareStatement("SELECT part FROM us_binary WHERE msgid = ? AND ident_nsid = ? "
|
||||
+ "AND ident_name = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,nsid);
|
||||
stmt.setString(3,name);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
{ // identity already exists, throw exception
|
||||
DatabaseException de = new DatabaseException(MessageOps_mysql.class,"UniStoreMessages","part.exists");
|
||||
de.setParameter(0,String.valueOf(msgid));
|
||||
throw de;
|
||||
|
||||
} // end if
|
||||
|
||||
SQLUtils.shutdown(rs);
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// get the part number for this part
|
||||
stmt = conn.prepareStatement("SELECT IFNULL(MAX(part),0) FROM us_binary WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
rs = stmt.executeQuery();
|
||||
int partnum = SQLUtils.getReturnCountInt(rs,1) + 1;
|
||||
|
||||
SQLUtils.shutdown(rs);
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// perform the insert!
|
||||
stmt = conn.prepareStatement("INSERT INTO us_binary (msgid, part, ident_nsid, ident_name, mimetype, datalen, "
|
||||
+ "filename, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,partnum);
|
||||
stmt.setInt(3,nsid);
|
||||
stmt.setString(4,name);
|
||||
stmt.setString(5,mimetype);
|
||||
stmt.setInt(6,length);
|
||||
stmt.setString(7,filename);
|
||||
stmt.setBinaryStream(8,data,length);
|
||||
stmt.executeUpdate();
|
||||
|
||||
return partnum;
|
||||
|
||||
} // 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 createBinaryPart
|
||||
|
||||
void delete(long msgid) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
Statement stmt2 = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// lock the tables
|
||||
stmt2 = conn.createStatement();
|
||||
stmt2.executeUpdate("LOCK TABLES us_head WRITE, us_prop WRITE, us_text WRITE, us_text_prop WRITE, "
|
||||
+ "us_binary WRITE, us_binary_prop WRITE;");
|
||||
|
||||
// delete all data from the tables
|
||||
stmt = conn.prepareStatement("DELETE FROM us_head WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_prop WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_text WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_text_prop WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_binary WHERE msgid = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_binary_prop WHERE msgid = ?;");
|
||||
stmt.setLong(1,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(stmt);
|
||||
SQLUtils.shutdown(stmt2);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end delete
|
||||
|
||||
Map listTextParts(long msgid) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// run the statement that lists the parts
|
||||
stmt = conn.prepareStatement("SELECT part, ident_nsid, ident_name FROM us_text WHERE msgid = ? ORDER BY part;");
|
||||
stmt.setLong(1,msgid);
|
||||
rs = stmt.executeQuery();
|
||||
|
||||
// create and return the listing
|
||||
TreeMap rc = new TreeMap();
|
||||
while (rs.next())
|
||||
rc.put(new Integer(rs.getInt(1)),new PropertyKey(rs.getInt(2),rs.getString(3)));
|
||||
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 listTextParts
|
||||
|
||||
Map listBinaryParts(long msgid) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// run the statement that lists the parts
|
||||
stmt = conn.prepareStatement("SELECT part, ident_nsid, ident_name FROM us_binary WHERE msgid = ? "
|
||||
+ "ORDER BY part;");
|
||||
stmt.setLong(1,msgid);
|
||||
rs = stmt.executeQuery();
|
||||
|
||||
// create and return the listing
|
||||
TreeMap rc = new TreeMap();
|
||||
while (rs.next())
|
||||
rc.put(new Integer(rs.getInt(1)),new PropertyKey(rs.getInt(2),rs.getString(3)));
|
||||
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 listTextParts
|
||||
|
||||
} // end class MessageOps_mysql
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.io.*;
|
|||
import java.lang.ref.*;
|
||||
import java.util.*;
|
||||
import org.apache.commons.collections.*;
|
||||
import com.silverwrist.dynamo.Namespaces;
|
||||
import com.silverwrist.dynamo.db.NamespaceCache;
|
||||
import com.silverwrist.dynamo.event.*;
|
||||
import com.silverwrist.dynamo.except.*;
|
||||
|
@ -49,7 +50,7 @@ class TextPartImpl implements UniStoreTextPart
|
|||
private SoftReference m_text = null;
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
* Constructors
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -76,6 +77,36 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
} // end constructor
|
||||
|
||||
TextPartImpl(PostDynamicUpdate post, MessageImpl parent, int part, QualifiedNameKey identity)
|
||||
{
|
||||
m_ops = null;
|
||||
m_nscache = null;
|
||||
m_post = post;
|
||||
m_parent = parent;
|
||||
m_part = part;
|
||||
m_identity = identity;
|
||||
m_mimetype = null;
|
||||
m_size = -1;
|
||||
m_linecount = -1;
|
||||
m_nread = 0;
|
||||
m_lastread = null;
|
||||
m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Overrides from class Object
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (m_ops==null)
|
||||
return "(deleted text part)";
|
||||
return "message " + m_parent.getMessageID() + ", text part " + m_identity.toString();
|
||||
|
||||
} // end toString
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface ObjectProvider
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -90,6 +121,8 @@ class TextPartImpl implements UniStoreTextPart
|
|||
*/
|
||||
public Object getObject(String namespace, String name)
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new NoSuchObjectException(this.toString(),namespace,name);
|
||||
try
|
||||
{ // convert the namespace name to an ID here
|
||||
PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name);
|
||||
|
@ -141,6 +174,8 @@ class TextPartImpl implements UniStoreTextPart
|
|||
public Object setObject(DynamoUser caller, String namespace, String name, Object value)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,namespace,"set.property","no.setProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -174,6 +209,8 @@ class TextPartImpl implements UniStoreTextPart
|
|||
public Object removeObject(DynamoUser caller, String namespace, String name)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,namespace,"remove.property","no.removeProperty");
|
||||
Object rc = null;
|
||||
// convert the namespace name to an ID here
|
||||
|
@ -201,6 +238,9 @@ class TextPartImpl implements UniStoreTextPart
|
|||
*/
|
||||
public Collection getNamespaces() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// call through to the database to get the list of namespace IDs
|
||||
int[] ids = m_ops.getPropertyNamespaceIDs(m_parent.getMessageID(),m_part);
|
||||
|
||||
|
@ -222,6 +262,9 @@ class TextPartImpl implements UniStoreTextPart
|
|||
*/
|
||||
public Collection getNamesForNamespace(String namespace) throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
// 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);
|
||||
|
@ -252,7 +295,7 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
public long getMessageID()
|
||||
{
|
||||
return m_parent.getMessageID();
|
||||
return (m_parent==null) ? -1L : m_parent.getMessageID();
|
||||
|
||||
} // end getMessageID
|
||||
|
||||
|
@ -300,6 +343,8 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
public void touchRead() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
synchronized (this)
|
||||
{ // touch the database, then the local values
|
||||
java.util.Date tmp = m_ops.touchRead(m_parent.getMessageID(),m_part);
|
||||
|
@ -312,6 +357,22 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
} // end touchRead
|
||||
|
||||
public synchronized void delete(DynamoUser caller) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
m_parent.testPermission(caller,Namespaces.UNISTORE_PERMISSIONS_NAMESPACE,"delete.part","no.deletePart");
|
||||
|
||||
// Cut this object loose from the parent.
|
||||
m_parent.deletedTextPart(m_part,m_identity);
|
||||
|
||||
// Zap it from the database.
|
||||
m_ops.delete(m_parent.getMessageID(),m_part);
|
||||
|
||||
baleeted(); // BALEETED!
|
||||
|
||||
} // end delete
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface UniStoreTextPart
|
||||
*--------------------------------------------------------------------------------
|
||||
|
@ -325,6 +386,8 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
public synchronized String getText() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
String rc = null;
|
||||
if (m_text!=null)
|
||||
rc = (String)(m_text.get());
|
||||
|
@ -341,8 +404,58 @@ class TextPartImpl implements UniStoreTextPart
|
|||
|
||||
public Reader getTextAsReader() throws DatabaseException
|
||||
{
|
||||
if (m_ops==null)
|
||||
throw new DatabaseException(TextPartImpl.class,"UniStoreMessages","part.deleted");
|
||||
return new StringReader(this.getText());
|
||||
|
||||
} // end getTextAsReader
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void precacheText(String txt)
|
||||
{
|
||||
m_text = new SoftReference(txt);
|
||||
|
||||
} // end txt
|
||||
|
||||
void resetPartNumber(int new_num)
|
||||
{
|
||||
m_part = new_num;
|
||||
|
||||
} // end resetPartNumber
|
||||
|
||||
/**
|
||||
* Called after the part has been deleted, either alone or through the entire message being deleted. This
|
||||
* method nulls out the internal data of the object and posts a "part-deleted" notification.<P>
|
||||
* See <A HREF="http://www.homestarrunner.com/sbemail50.html">this page</A> for the source of the method name.
|
||||
*/
|
||||
synchronized void baleeted()
|
||||
{
|
||||
// Cut loose most of our data before we post an update event.
|
||||
m_ops = null;
|
||||
m_nscache = null;
|
||||
m_mimetype = null;
|
||||
m_size = -1;
|
||||
m_linecount = -1;
|
||||
m_nread = 0;
|
||||
m_lastread = null;
|
||||
m_properties.clear();
|
||||
if (m_text!=null)
|
||||
m_text.clear();
|
||||
m_text = null;
|
||||
|
||||
// Post the "deleted" notification event.
|
||||
m_post.postUpdate(new MessagePartDeletedEvent(this));
|
||||
|
||||
// Now cut loose the rest of our data.
|
||||
m_post = null;
|
||||
m_parent = null;
|
||||
m_part = -1;
|
||||
m_identity = null;
|
||||
|
||||
} // end baleeted
|
||||
|
||||
} // end class TextPartImpl
|
||||
|
|
|
@ -55,4 +55,6 @@ abstract class TextPartOps extends OpsBase
|
|||
|
||||
abstract String getText(long msgid, int part) throws DatabaseException;
|
||||
|
||||
abstract void delete(long msgid, int part) throws DatabaseException;
|
||||
|
||||
} // end class TextPartOps
|
||||
|
|
|
@ -455,4 +455,57 @@ class TextPartOps_mysql extends TextPartOps
|
|||
|
||||
} // end getText
|
||||
|
||||
void delete(long msgid, int part) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
Statement stmt2 = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// lock the tables
|
||||
stmt2 = conn.createStatement();
|
||||
stmt2.executeUpdate("LOCK TABLES us_text WRITE, us_text_props WRITE;");
|
||||
|
||||
// delete all entries from the main and property tables
|
||||
stmt = conn.prepareStatement("DELETE FROM us_text WHERE msgid = ? AND part = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("DELETE FROM us_text_prop WHERE msgid = ? AND part = ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
|
||||
// renumber all entries above that one to close the gap
|
||||
stmt = conn.prepareStatement("UPDATE us_text SET part = part - 1 WHERE msgid = ? AND part > ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
stmt.executeUpdate();
|
||||
stmt.close();
|
||||
stmt = conn.prepareStatement("UPDATE us_text_prop SET part = part - 1 WHERE msgid = ? AND part > ?;");
|
||||
stmt.setLong(1,msgid);
|
||||
stmt.setInt(2,part);
|
||||
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(stmt);
|
||||
SQLUtils.shutdown(stmt2);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end delete
|
||||
|
||||
} // end class TextPartOps_mysql
|
||||
|
|
|
@ -24,6 +24,7 @@ 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.event.*;
|
||||
import com.silverwrist.dynamo.except.*;
|
||||
import com.silverwrist.dynamo.iface.*;
|
||||
import com.silverwrist.dynamo.security.SecurityReferenceMonitor;
|
||||
|
@ -38,6 +39,9 @@ public class UniStoreManager implements NamedObject, ComponentInitialize, Compon
|
|||
|
||||
private static Logger logger = Logger.getLogger(UniStoreManager.class);
|
||||
|
||||
private static final Long NO_PARENT = new Long(0);
|
||||
private static final Integer NO_SEQ = new Integer(0);
|
||||
|
||||
private static int DEFAULT_MSGCACHE_HARD = 100;
|
||||
private static int DEFAULT_MSGCACHE_SOFT = 1000;
|
||||
|
||||
|
@ -190,9 +194,46 @@ public class UniStoreManager implements NamedObject, ComponentInitialize, Compon
|
|||
m_msgcache.put(key,rc);
|
||||
|
||||
} // end if
|
||||
else if (rc.getMessageID()!=msgid)
|
||||
{ // This only happens when the message has been deleted but its object still lingers in the cache. Make
|
||||
// sure the cache entry is removed and throw an error.
|
||||
m_msgcache.remove(key);
|
||||
DatabaseException de = new DatabaseException(UniStoreManager.class,"UniStoreMessages","no.message");
|
||||
de.setParameter(0,String.valueOf(msgid));
|
||||
throw de;
|
||||
|
||||
} // end else if.
|
||||
|
||||
return rc;
|
||||
|
||||
} // end getMessage
|
||||
|
||||
public UniStoreMessage createMessage(DynamoUser caller) throws DatabaseException
|
||||
{
|
||||
// Call down to the database to create the record.
|
||||
java.util.Date tick = new java.util.Date();
|
||||
long newid = m_ops.createMessage(caller.getUID(),tick);
|
||||
|
||||
// Fake up a parameter buffer and use it to create the MessageImpl object.
|
||||
Long key = new Long(newid);
|
||||
HashMap params = new HashMap();
|
||||
params.put(ManagerOps.PARAM_MSGID,key);
|
||||
params.put(ManagerOps.PARAM_PARENT,NO_PARENT);
|
||||
params.put(ManagerOps.PARAM_SEQ,NO_SEQ);
|
||||
params.put(ManagerOps.PARAM_CREATOR,new Integer(caller.getUID()));
|
||||
params.put(ManagerOps.PARAM_POSTED,tick);
|
||||
MessageImpl rc = new MessageImpl(m_ops.getMessageOps(),m_ns_cache,m_srm,m_users,m_post,params);
|
||||
rc.zeroCounts();
|
||||
|
||||
synchronized (this)
|
||||
{ // add the new message object to the cache
|
||||
m_msgcache.put(key,rc);
|
||||
|
||||
} // end synchronized block
|
||||
|
||||
m_post.postUpdate(new MessageCreatedEvent(rc));
|
||||
return rc;
|
||||
|
||||
} // end createMessage
|
||||
|
||||
} // end class UniStoreManager
|
||||
|
|
|
@ -26,3 +26,9 @@ bad.loadText.part=Unable to find text part #{0} of message #{1} in the Universal
|
|||
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.
|
||||
no.createPart=You are not authorized to create a new part in message #{0} in the Universal Message Store.
|
||||
part.exists=A part with this identity already exists in message #{0}.
|
||||
no.deletePart=You are not authorized to delete a part from message #{0} in the Universal Message Store.
|
||||
part.deleted=This part has been deleted.
|
||||
no.deleteMessage=You are not authorized to delete message #{0} in the Universal Message Store.
|
||||
message.deleted=This message has been deleted.
|
||||
|
|
Loading…
Reference in New Issue
Block a user