vincenzo 2003/07/15 03:12:45 Modified: src/conf Tag: branch_2_1_fcs sqlResources.xml src/java/org/apache/james/core Tag: branch_2_1_fcs MailImpl.java src/java/org/apache/james/mailrepository Tag: branch_2_1_fcs JDBCMailRepository.java src/java/org/apache/mailet Tag: branch_2_1_fcs Mail.java Log: Adding mail attributes support. Revision Changes Path No revision No revision 1.16.4.5 +52 -2 james-server/src/conf/sqlResources.xml Index: sqlResources.xml =================================================================== RCS file: /home/cvs/james-server/src/conf/sqlResources.xml,v retrieving revision 1.16.4.4 retrieving revision 1.16.4.5 diff -u -r1.16.4.4 -r1.16.4.5 --- sqlResources.xml 23 Jun 2003 00:56:12 -0000 1.16.4.4 +++ sqlResources.xml 15 Jul 2003 10:12:44 -0000 1.16.4.5 @@ -171,8 +171,23 @@ <!-- Statements used to update the body of a message stored in this repository. --> <sql name="updateMessageBodySQL">UPDATE ${table} SET message_body = ? WHERE message_name = ? AND repository_name = ?</sql> + <!-- Statements used to update the attributes of a message stored in this repository. --> + <!-- Uncomment this statement to activate the attributes support. + <sql name="updateMessageAttributesSQL">UPDATE ${table} SET message_attributes = ? WHERE message_name = ? AND repository_name = ?</sql> + --> + <!-- Statements used to insert a message into this repository. --> - <sql name="insertMessageSQL">INSERT INTO ${table} (message_name, repository_name, message_state, error_message, sender, recipients, remote_host, remote_addr, last_updated, message_body) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)</sql> + <sql name="insertMessageSQL">INSERT INTO ${table} (message_name, + repository_name, message_state, error_message, sender, recipients, + remote_host, remote_addr, last_updated, message_body) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)</sql> + + <!-- Statements used to insert a message with attributes into this repository. --> + <!-- Uncomment this statement and comment the previous one to activate the attributes support. + <sql name="insertMessageSQL">INSERT INTO ${table} (message_name, + repository_name, message_state, error_message, sender, recipients, + remote_host, remote_addr, last_updated, message_body, + message_attributes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)</sql> + --> <!-- Statements used to retrieve a message stored in this repository. --> <sql name="retrieveMessageSQL">SELECT message_state, error_message, sender, recipients, remote_host, remote_addr, last_updated FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> @@ -180,6 +195,11 @@ <!-- Statements used to retrieve the body of a message stored in this repository. --> <sql name="retrieveMessageBodySQL">SELECT message_body FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> + <!-- Statements used to retrieve the attributes of a message stored in this repository. --> + <!-- Uncomment this statement to activate the attributes support. + <sql name="retrieveMessageAttributesSQL">SELECT message_attributes FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> + --> + <!-- Statements used to retrieve the size of the body of a message stored in this repository. --> <!-- NOTE: This statement is optional and need not be implemented for a particular database to be supported. --> <sql name="retrieveMessageBodySizeSQL" db="mssql">SELECT datalength(message_body) FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> @@ -205,6 +225,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body longblob NOT NULL , + message_attributes longblob NOT NULL , last_updated datetime NOT NULL, PRIMARY KEY (repository_name, message_name) ) @@ -220,6 +241,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body varchar NOT NULL , + message_attributes varchar NOT NULL , last_updated timestamp NOT NULL, PRIMARY KEY (repository_name, message_name) ) @@ -235,6 +257,7 @@ [remote_host] [varchar] (255) NOT NULL , [remote_addr] [varchar] (20) NOT NULL , [message_body] [image] NOT NULL , + [message_attributes] [image] NOT NULL , [last_updated] [datetime] NOT NULL, PRIMARY KEY (repository_name, message_name) ) @@ -250,6 +273,7 @@ remote_host varchar2(100) NOT NULL , remote_addr varchar2(20) NOT NULL , message_body long raw NOT NULL , + message_attributes long raw NOT NULL , last_updated date NOT NULL , PRIMARY KEY (repository_name, message_name) ) @@ -266,6 +290,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body bytea NOT NULL , + message_attributes bytea NOT NULL , last_updated timestamp NOT NULL, PRIMARY KEY (repository_name, message_name) ) @@ -281,6 +306,7 @@ remote_host varchar (100) NOT NULL , remote_addr varchar (20) NOT NULL , message_body long byte NOT NULL , + message_attributes long byte NOT NULL , last_updated date NOT NULL, PRIMARY KEY (repository_name, message_name) ) @@ -302,8 +328,21 @@ <!-- Statements used to update the body of a message stored in this repository. --> <sql name="updateMessageBodySQL">UPDATE ${table} SET message_body = ? WHERE message_name = ? AND repository_name = ?</sql> + <!-- Statements used to update the attributes of a message stored in this repository. --> + <!-- Uncomment this statement to activate the attributes support. + <sql name="updateMessageAttributesSQL">UPDATE ${table} SET message_attributes = ? WHERE message_name = ? AND repository_name = ?</sql> + --> + <!-- Statements used to insert a message into this repository. --> <sql name="insertMessageSQL">INSERT INTO ${table} (message_name, repository_name, message_state, error_message, sender, recipients, remote_host, remote_addr, last_updated, message_body) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)</sql> + + <!-- Statements used to insert a message with attributes into this repository. --> + <!-- Uncomment this statement and comment the previous one to activate the attributes support. + <sql name="insertMessageSQL">INSERT INTO ${table} (message_name, + repository_name, message_state, error_message, sender, recipients, + remote_host, remote_addr, last_updated, message_body, + message_attributes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)</sql> + --> <!-- Statements used to retrieve a message stored in this repository. --> <sql name="retrieveMessageSQL">SELECT message_state, error_message, sender, recipients, remote_host, remote_addr, last_updated FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> @@ -311,6 +350,11 @@ <!-- Statements used to retrieve the body of a message stored in this repository. --> <sql name="retrieveMessageBodySQL">SELECT message_body FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> + <!-- Statements used to retrieve the attributes of a message stored in this repository. --> + <!-- Uncomment this statement to activate the attributes support. + <sql name="retrieveMessageAttributesSQL">SELECT message_attributes FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> + --> + <!-- Statements used to retrieve the size of the body of a message stored in this repository. --> <!-- NOTE: This statement is optional and need not be implemented for a particular database to be supported. --> <sql name="retrieveMessageBodySizeSQL" db="mssql">SELECT datalength(message_body) FROM ${table} WHERE message_name = ? AND repository_name = ?</sql> @@ -336,6 +380,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body varchar NOT NULL , + message_attributes varchar NOT NULL , last_updated timestamp NOT NULL, PRIMARY KEY (message_name, repository_name) ) @@ -351,6 +396,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body longblob NOT NULL , + message_attributes longblob NOT NULL , last_updated datetime NOT NULL, PRIMARY KEY (message_name, repository_name) ) @@ -366,8 +412,9 @@ [remote_host] [varchar] (255) NOT NULL , [remote_addr] [varchar] (20) NOT NULL , [message_body] [image] NOT NULL , + [message_attributes] [image] NOT NULL , [last_updated] [datetime] NOT NULL, - PRIMARY KEY (repository_name, message_name) + PRIMARY KEY (message_name, repository_name) ) </sql> <sql name="createTable" db="oracle"> @@ -381,6 +428,7 @@ remote_host varchar2(255) NOT NULL , remote_addr varchar2(20) NOT NULL , message_body long raw NOT NULL , + message_attributes long raw NOT NULL , last_updated date NOT NULL , PRIMARY KEY (message_name, repository_name) ) @@ -396,6 +444,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body bytea NOT NULL , + message_attributes bytea NOT NULL , last_updated timestamp NOT NULL, PRIMARY KEY (message_name, repository_name) ) @@ -411,6 +460,7 @@ remote_host varchar (255) NOT NULL , remote_addr varchar (20) NOT NULL , message_body long byte NOT NULL , + message_attributes long byte NOT NULL , last_updated date NOT NULL, PRIMARY KEY (message_name, repository_name) ) No revision No revision 1.17.4.3 +78 -5 james-server/src/java/org/apache/james/core/MailImpl.java Index: MailImpl.java =================================================================== RCS file: /home/cvs/james-server/src/java/org/apache/james/core/MailImpl.java,v retrieving revision 1.17.4.2 retrieving revision 1.17.4.3 diff -u -r1.17.4.2 -r1.17.4.3 --- MailImpl.java 8 Mar 2003 21:54:03 -0000 1.17.4.2 +++ MailImpl.java 15 Jul 2003 10:12:44 -0000 1.17.4.3 @@ -77,14 +77,12 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; +import java.util.HashMap; /** * Wraps a MimeMessage adding routing information (from SMTP) and some simple * API enhancements. - * @author Federico Barbieri <[EMAIL PROTECTED]> - * @author Serge Knystautas <[EMAIL PROTECTED]> - * @author Stuart Roebuck <[EMAIL PROTECTED]> - * @version 0.9 + * @version CVS $Revision$ $Date$ */ public class MailImpl implements Disposable, Mail { /** @@ -129,10 +127,15 @@ */ private Date lastUpdated = new Date(); /** + * Attributes added to this MailImpl instance + */ + private HashMap attributes; + /** * A constructor that creates a new, uninitialized MailImpl */ public MailImpl() { setState(Mail.DEFAULT); + attributes = new HashMap(); } /** * A constructor that creates a MailImpl with the specified name, @@ -230,6 +233,7 @@ newMail.setRemoteHost(remoteHost); newMail.setRemoteAddr(remoteAddr); newMail.setLastUpdated(lastUpdated); + newMail.setAttributesRaw((HashMap) attributes.clone()); return newMail; } catch (MessagingException me) { // Ignored. Return null in the case of an error. @@ -515,7 +519,15 @@ name = (String) in.readObject(); remoteHost = (String) in.readObject(); remoteAddr = (String) in.readObject(); - setLastUpdated((Date) in.readObject()); + Object o = in.readObject(); + //this check is done to be backwards compatible with mail repositories + if (o instanceof Date) { + setLastUpdated((Date)o); + attributes = new HashMap(); + } else { + attributes = (HashMap)o; + setLastUpdated((Date) in.readObject()); + } } /** * Write the MailImpl to an <code>ObjectOutputStream</code>. @@ -533,6 +545,7 @@ out.writeObject(name); out.writeObject(remoteHost); out.writeObject(remoteAddr); + out.writeObject(attributes); out.writeObject(lastUpdated); } @@ -550,4 +563,64 @@ } } + /** + * This method is necessary, when Mail repositories needs to deal + * explicitly with storing Mail attributes as a Serializable + * Note: This method is not exposed in the Mail interface, + * it is for internal use by James only. + * @return Serializable of the entire attributes collection + **/ + public HashMap getAttributesRaw () + { + return attributes; + } + + /** + * This method is necessary, when Mail repositories needs to deal + * explicitly with retriving Mail attributes as a Serializable + * Note: This method is not exposed in the Mail interface, + * it is for internal use by James only. + * @return Serializable of the entire attributes collection + **/ + public void setAttributesRaw (HashMap attr) + { + this.attributes = (attr == null) ? new HashMap() : attr; + } + + /** + * @see org.apache.mailet.Mail#getAttribute(String) + */ + public Serializable getAttribute(String key) { + return (Serializable)attributes.get(key); + } + /** + * @see org.apache.mailet.Mail#setAttribute(String,Serializable) + */ + public Serializable setAttribute(String key, Serializable object) { + return (Serializable)attributes.put(key, object); + } + /** + * @see org.apache.mailet.Mail#removeAttribute(String) + */ + public Serializable removeAttribute(String key) { + return (Serializable)attributes.remove(key); + } + /** + * @see org.apache.mailet.Mail#removeAllAttributes() + */ + public void removeAllAttributes() { + attributes.clear(); + } + /** + * @see org.apache.mailet.Mail#getAttributeNames() + */ + public Iterator getAttributeNames() { + return attributes.keySet().iterator(); + } + /** + * @see org.apache.mailet.Mail#hasAttributes() + */ + public boolean hasAttributes() { + return !attributes.isEmpty(); + } } No revision No revision 1.30.4.7 +143 -2 james-server/src/java/org/apache/james/mailrepository/JDBCMailRepository.java Index: JDBCMailRepository.java =================================================================== RCS file: /home/cvs/james-server/src/java/org/apache/james/mailrepository/JDBCMailRepository.java,v retrieving revision 1.30.4.6 retrieving revision 1.30.4.7 diff -u -r1.30.4.6 -r1.30.4.7 --- JDBCMailRepository.java 31 May 2003 23:42:29 -0000 1.30.4.6 +++ JDBCMailRepository.java 15 Jul 2003 10:12:45 -0000 1.30.4.7 @@ -89,6 +89,8 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; import java.io.OutputStream; import java.sql.*; import java.util.*; @@ -107,7 +109,7 @@ * * <p>Requires a logger called MailRepository. * - * @version 1.0.0, 24/04/1999 + * @version CVS $Revision$ $Date$ */ public class JDBCMailRepository extends AbstractLogEnabled @@ -537,6 +539,43 @@ theJDBCUtil.closeJDBCStatement(localUpdateMessage); } + //Determine whether attribues are used and available for storing + //Do we have updateMessageAttributesSQL? + String updateMessageAttrSql = + sqlQueries.getSqlString("updateMessageAttributesSQL", false); + if (updateMessageAttrSql!=null && mc.hasAttributes()) { + PreparedStatement updateMessageAttr = null; + try { + updateMessageAttr = + conn.prepareStatement(updateMessageAttrSql); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + try { + oos.writeObject(((MailImpl)mc).getAttributesRaw()); + oos.flush(); + ByteArrayInputStream attrInputStream = + new ByteArrayInputStream(baos.toByteArray()); + updateMessageAttr.setBinaryStream(1, attrInputStream, baos.size()); + } finally { + try { + if (oos != null) { + oos.close(); + } + } catch (IOException ioe) { + getLogger().debug("JDBCMailRepository: Unexpected exception while closing output stream."); + } + } + updateMessageAttr.setString(2, mc.getName()); + updateMessageAttr.setString(3, repositoryName); + updateMessageAttr.execute(); + } catch (SQLException sqle) { + getLogger().info("JDBCMailRepository: Trying to update mail attributes failed.",sqle); + + } finally { + theJDBCUtil.closeJDBCStatement(updateMessageAttr); + } + } + //Determine whether the message body has changed, and possibly avoid // updating the database. MimeMessage messageBody = mc.getMessage(); @@ -585,8 +624,10 @@ //Insert the record into the database PreparedStatement insertMessage = null; try { + String insertMessageSQL = sqlQueries.getSqlString("insertMessageSQL", true); + int number_of_parameters = getNumberOfParameters (insertMessageSQL); insertMessage = - conn.prepareStatement(sqlQueries.getSqlString("insertMessageSQL", true)); + conn.prepareStatement(insertMessageSQL); insertMessage.setString(1, mc.getName()); insertMessage.setString(2, repositoryName); insertMessage.setString(3, mc.getState()); @@ -631,6 +672,28 @@ closeOutputStreams(headerOut, bodyOut); } //Store the headers in the database + + //Store attributes + if (number_of_parameters > 10) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + try { + oos.writeObject(((MailImpl)mc).getAttributesRaw()); + oos.flush(); + ByteArrayInputStream attrInputStream = + new ByteArrayInputStream(baos.toByteArray()); + insertMessage.setBinaryStream(11, attrInputStream, baos.size()); + } finally { + try { + if (oos != null) { + oos.close(); + } + } catch (IOException ioe) { + getLogger().debug("JDBCMailRepository: Unexpected exception while closing output stream."); + } + } + } + insertMessage.execute(); } finally { theJDBCUtil.closeJDBCStatement(insertMessage); @@ -692,7 +755,68 @@ } return null; } + //Determine whether attribues are used and retrieve them + //Do we have retrieveAttributesSQL? + String retrieveMessageAttrSql = + sqlQueries.getSqlString("retrieveMessageAttributesSQL", false); + PreparedStatement retrieveMessageAttr = null; + HashMap attributes = null; + if (retrieveMessageAttrSql!=null) { + ResultSet rsMessageAttr = null; + try { + retrieveMessageAttr = + conn.prepareStatement(retrieveMessageAttrSql); + + retrieveMessageAttr.setString(1, key); + retrieveMessageAttr.setString(2, repositoryName); + rsMessageAttr = retrieveMessageAttr.executeQuery(); + + if (rsMessageAttr.next()) { + try { + byte[] serialized_attr = rsMessageAttr.getBytes(1); + ByteArrayInputStream bais = new ByteArrayInputStream (serialized_attr); + ObjectInputStream ois = new ObjectInputStream (bais); + attributes = (HashMap)ois.readObject(); + ois.close(); + } catch (IOException ioe) { + if (getLogger().isDebugEnabled()) { + StringBuffer debugBuffer = + new StringBuffer(64) + .append("Exception reading attributes ") + .append(key) + .append(" in ") + .append(repositoryName); + getLogger().debug(debugBuffer.toString(), ioe); + } + } + } else { + if (getLogger().isDebugEnabled()) { + StringBuffer debugBuffer = + new StringBuffer(64) + .append("Did not find a record (attributes) ") + .append(key) + .append(" in ") + .append(repositoryName); + getLogger().debug(debugBuffer.toString()); + } + } + } catch (SQLException sqle) { + synchronized (System.err) { + System.err.println("Error retrieving message"); + System.err.println(sqle.getMessage()); + System.err.println(sqle.getErrorCode()); + System.err.println(sqle.getSQLState()); + System.err.println(sqle.getNextException()); + sqle.printStackTrace(); + } + } finally { + theJDBCUtil.closeJDBCResultSet(rsMessageAttr); + theJDBCUtil.closeJDBCStatement(retrieveMessageAttr); + } + } + MailImpl mc = new MailImpl(); + mc.setAttributesRaw (attributes); mc.setName(key); mc.setState(rsMessage.getString(1)); mc.setErrorMessage(rsMessage.getString(2)); @@ -847,6 +971,23 @@ } return result; } + + /** + * This method calculates number of parameters in a prepared statement SQL String. + * It does so by counting the number of '?' in the string + * @param sqlstring to return parameter count for + * @return number of parameters + **/ + private int getNumberOfParameters (String sqlstring) { + //it is alas a java 1.4 feature to be able to call + //getParameterMetaData which could provide us with the parameterCount + char[] chars = sqlstring.toCharArray(); + int count = 0; + for (int i = 0; i < chars.length; i++) { + count += chars[i]=='?' ? 1 : 0; + } + return count; + } /** * Closes output streams used to update message No revision No revision 1.3.4.3 +67 -3 james-server/src/java/org/apache/mailet/Mail.java Index: Mail.java =================================================================== RCS file: /home/cvs/james-server/src/java/org/apache/mailet/Mail.java,v retrieving revision 1.3.4.2 retrieving revision 1.3.4.3 diff -u -r1.3.4.2 -r1.3.4.3 --- Mail.java 8 Mar 2003 21:54:13 -0000 1.3.4.2 +++ Mail.java 15 Jul 2003 10:12:45 -0000 1.3.4.3 @@ -62,6 +62,7 @@ import javax.mail.internet.MimeMessage; import java.io.Serializable; import java.util.Collection; +import java.util.Iterator; /** * Wrap a MimeMessage with routing information (from SMTP) such @@ -70,9 +71,7 @@ * which processor in the mailet container it is currently running. * Special processor names are "root" and "error". * - * @author Federico Barbieri <[EMAIL PROTECTED]> - * @author Serge Knystautas <[EMAIL PROTECTED]> - * @version 0.9 + * @version CVS $Revision$ $Date$ */ public interface Mail extends Serializable, Cloneable { String GHOST = "ghost"; @@ -150,4 +149,69 @@ * @param state - the new state of this message */ void setState(String state); + + /** + * Returns the Mail session attribute with the given name, or null + * if there is no attribute by that name. + * An attribute allows a mailet to give this Mail instance additional information + * not already provided by this interface.<p> + * A list of currently set attributes can be retrieved using getAttributeNames. + * <p> + * The attribute is returned as a java.lang.Object or some subclass. Attribute + * names should follow the same convention as package names. The Java Mailet API + * specification reserves names matching java.*, javax.*, and sun.* + * + * @param name - a String specifying the name of the attribute + * @return an Object containing the value of the attribute, or null if no attribute + * exists matching the given name + */ + Serializable getAttribute(String name); + + /** + * Returns an Iterator containing the attribute names currently available within + * this Mail instance. Use the getAttribute(java.lang.String) method with an + * attribute name to get the value of an attribute. + * + * @return an Iterator of attribute names + */ + Iterator getAttributeNames(); + + /** + * @return true if this Mail instance has any attributes set. + **/ + boolean hasAttributes(); + + /** + * Removes the attribute with the given name from this Mail instance. After + * removal, subsequent calls to getAttribute(java.lang.String) to retrieve + * the attribute's value will return null. + * + * @param name - a String specifying the name of the attribute to be removed + * @return previous attribute value associated with specified name, or null + * if there was no mapping for name (null can also mean that null + * was bound to the name) + */ + Serializable removeAttribute(String name); + + /** + * Removes all the attributes associated with this Mail instance. + **/ + void removeAllAttributes(); + + /** + * Binds an object to a given attribute name in this Mail instance. If the name + * specified is already used for an attribute, this method will remove the old + * attribute and bind the name to the new attribute. + * As instances of Mail is Serializable, it is necessary that the attributes being + * Serializable as well + * <p> + * Attribute names should follow the same convention as package names. The Java + * Mailet API specification reserves names matching java.*, javax.*, and sun.*. + * + * @param name - a String specifying the name of the attribute + * @param object - a Serializable Object representing the attribute to be bound + * @return the object previously bound to the name, null if the name was + * not bound (null can also mean that null was bound to the name) + */ + Serializable setAttribute(String name, Serializable object); }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]