vincenzo 2003/07/15 03:11:59 Modified: src/conf sqlResources.xml src/java/org/apache/james/core MailImpl.java src/java/org/apache/james/mailrepository JDBCMailRepository.java src/java/org/apache/mailet Mail.java Log: Adding mail attributes support. Revision Changes Path 1.20 +51 -1 james-server/src/conf/sqlResources.xml Index: sqlResources.xml =================================================================== RCS file: /home/cvs/james-server/src/conf/sqlResources.xml,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- sqlResources.xml 23 Jun 2003 01:53:27 -0000 1.19 +++ sqlResources.xml 15 Jul 2003 10:11:57 -0000 1.20 @@ -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,6 +412,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 (message_name, repository_name) ) @@ -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) ) 1.26 +38 -1 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.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- MailImpl.java 26 Apr 2003 10:00:54 -0000 1.25 +++ MailImpl.java 15 Jul 2003 10:11:58 -0000 1.26 @@ -87,7 +87,7 @@ /** * Wraps a MimeMessage adding routing information (from SMTP) and some simple * API enhancements. - * @version 0.9 + * @version CVS $Revision$ $Date$ */ public class MailImpl implements Disposable, Mail { /** @@ -238,6 +238,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. @@ -569,6 +570,30 @@ } /** + * 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) { @@ -587,9 +612,21 @@ 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(); } } 1.45 +144 -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.44 retrieving revision 1.45 diff -u -r1.44 -r1.45 --- JDBCMailRepository.java 1 Jun 2003 00:02:49 -0000 1.44 +++ JDBCMailRepository.java 15 Jul 2003 10:11:58 -0000 1.45 @@ -62,6 +62,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.Connection; import java.sql.DatabaseMetaData; @@ -120,7 +122,7 @@ * * <p>Requires a logger called MailRepository. * - * @version 1.0.0, 24/04/1999 + * @version CVS $Revision$ $Date$ */ public class JDBCMailRepository extends AbstractLogEnabled @@ -550,6 +552,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(); @@ -598,8 +637,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()); @@ -644,6 +685,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); @@ -705,7 +768,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)); @@ -845,6 +969,7 @@ ((repository.repositoryName == repositoryName) || ((repository.repositoryName != null) && repository.repositoryName.equals(repositoryName))); } + /** * Provide a hash code that is consistent with equals for this class * @@ -860,6 +985,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 1.10 +9 -1 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.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- Mail.java 26 Apr 2003 10:00:55 -0000 1.9 +++ Mail.java 15 Jul 2003 10:11:59 -0000 1.10 @@ -70,7 +70,7 @@ * which processor in the mailet container it is currently running. * Special processor names are "root" and "error". * - * @version 0.9 + * @version CVS $Revision$ $Date$ */ public interface Mail extends Serializable, Cloneable { String GHOST = "ghost"; @@ -189,6 +189,10 @@ */ 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. @@ -199,6 +203,10 @@ * 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
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]