/* * 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 . * * 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 , * 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 ObjectProvider. * * @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 SecureObjectStore. * * @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 SecureObjectStore. * @return The previous object that was set into the SecureObjectStore under this namespace and name, or * null 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 SecureObjectStore. */ 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 SecureObjectStore. * * @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 SecureObjectStore under this namespace and name, or * null 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 SecureObjectStore. */ 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 SecureObjectStore. * * @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; iSecureObjectStore 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