Re: Current state of mail feed code



On Thu, 2005-03-10 at 18:58 -0500, David Malcolm wrote:
> Attached is a full diff of my workspace against HEAD (walters wanted to
> work on it tonight)

Here's an updated patch with a lot of changes.  I had to change the core
Message bits so that we could increment the topic version.  Not sure if
this is the correct approach.

I removed the scraper for now, we can add it back later or do python
whichever seems better.  I just wanted to get the core injection
working.

Right now I've broken the tests for threaded injection and was in the
process of debugging that.


Index: build.xml
===================================================================
RCS file: /cvs/gnome/yarrr/build.xml,v
retrieving revision 1.21
diff -u -r1.21 build.xml
--- build.xml	4 Mar 2005 19:59:12 -0000	1.21
+++ build.xml	12 Mar 2005 00:12:06 -0000
@@ -21,6 +21,7 @@
 	<property name="tomcat.manager_url" value="${tomcat.url}/manager"/>
 	
 	<!-- Configure the custom Ant tasks for the Manager application -->
+	<!--
 	<taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask"/>
 	<taskdef name="list"      classname="org.apache.catalina.ant.ListTask"/>
 	<taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask"/>
@@ -29,6 +30,7 @@
 	<taskdef name="start"     classname="org.apache.catalina.ant.StartTask"/>
 	<taskdef name="stop"      classname="org.apache.catalina.ant.StopTask"/>
 	<taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask"/>
+	-->
 	
 	<target name="deploy" description="Install web application" depends="package-servlet">
 		<deploy url="${tomcat.manager_url}" username="${tomcat.username}" password="${tomcat.password}" path="${servlet.path}" war="${basedir}/${build}${servlet.path}.war"/>
Index: client/yarrr/window.py
===================================================================
RCS file: /cvs/gnome/yarrr/client/yarrr/window.py,v
retrieving revision 1.27
diff -u -r1.27 window.py
--- client/yarrr/window.py	11 Mar 2005 16:23:58 -0000	1.27
+++ client/yarrr/window.py	12 Mar 2005 00:12:06 -0000
@@ -50,6 +50,11 @@
         # urlparse seem to work only with known schemes
         http_uri = uri.replace ('yarrr', 'http', 1)
         (scheme, netloc, path, query, fragment) = urlparse.urlsplit (http_uri)
+        print scheme
+        print netloc
+        print path
+        print query
+        print fragment
         address = scheme + '://' + netloc + path
         for param in query.split ('&'):
             pair = param.split ('=')
Index: src/org/gnome/yarrr/Message.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/Message.java,v
retrieving revision 1.16
diff -u -r1.16 Message.java
--- src/org/gnome/yarrr/Message.java	9 Mar 2005 15:21:39 -0000	1.16
+++ src/org/gnome/yarrr/Message.java	12 Mar 2005 00:12:06 -0000
@@ -40,15 +40,31 @@
 	protected Message() {
 	}
 	
-	public Message(Timestamp sentTime, Person author, String subject, Long replyToId, Document document, Topic topic, boolean save) throws HibernateException {
+	/**
+	 * Construct a new unattached message.  Should be added to a topic before it is persisted.
+	 * 
+	 * @param sentTime
+	 * @param author
+	 * @param subject
+	 * @param replyToId
+	 * @param document
+	 */
+	public Message(Timestamp sentTime, Person author, String subject, Long replyToId, Document document) {
 		if (sentTime == null) 
 			this.sentTime = new Timestamp(new java.util.Date().getTime());
 		else
-			this.sentTime = sentTime;
+			this.sentTime = sentTime;	
 		this.author = author;
 		this.subject = subject;
 		this.replyToId = replyToId;
-		this.document = document;		
+		this.document = document;
+		/* We're not attached */
+		this.version = -1;
+		this.versionAtCreation = -1;
+	}
+	
+	public Message(Timestamp sentTime, Person author, String subject, Long replyToId, Document document, Topic topic, boolean save) throws HibernateException {
+		this(sentTime, author, subject, replyToId, document);
 		this.topic = topic;
 		this.version = topic.getVersion();
 		this.versionAtCreation = version;
@@ -108,7 +124,7 @@
 	public Topic getTopic() {
 		return topic;
 	}
-	private void setTopic(Topic topic) {
+	void setTopic(Topic topic) {
 		this.topic = topic;
 	}
 	public long getVersionAtCreation() {
Index: src/org/gnome/yarrr/Topic.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/Topic.java,v
retrieving revision 1.28
diff -u -r1.28 Topic.java
--- src/org/gnome/yarrr/Topic.java	10 Mar 2005 16:11:32 -0000	1.28
+++ src/org/gnome/yarrr/Topic.java	12 Mar 2005 00:12:06 -0000
@@ -198,6 +198,8 @@
         .setLong("clientVersion", clientVersion)
         .setLong("currentVersion", this.version)
         .list();
+        
+        //seems to NOT properly set up an EmailMessage if if returns one of these as the child.message
 	}
     
 	public List getNewLinksSince(long clientVersion) {
@@ -348,6 +350,14 @@
 
     public Message postMessage(Person author, String subject, Long replyToId, Document document) {
     	return postMessageWithTimestamp(author, subject, replyToId, document, null);
+    }
+    
+    public void postMessageUnlocked(Message m) {
+    	version = version + 1;
+    	m.setTopic(this);
+    	m.setVersion(version);
+    	HibernateUtil.getSession().save(m);
+    	this.lastPostTime = m.getSentTime();
     }
     
     public void removeMessage(long messageId) throws HibernateException {
Index: src/org/gnome/yarrr/Yarrr.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/Yarrr.java,v
retrieving revision 1.37
diff -u -r1.37 Yarrr.java
--- src/org/gnome/yarrr/Yarrr.java	4 Mar 2005 19:59:14 -0000	1.37
+++ src/org/gnome/yarrr/Yarrr.java	12 Mar 2005 00:12:06 -0000
@@ -4,9 +4,7 @@
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
-import org.hibernate.HibernateException;
-import org.hibernate.cfg.Configuration;
-import org.hibernate.tool.hbm2ddl.SchemaUpdate;
+
 import org.apache.log4j.Logger;
 import org.apache.log4j.PropertyConfigurator;
 import org.gnome.yarrr.IInitializer.CreationException;
@@ -16,6 +14,10 @@
 import org.gnome.yarrr.hibernate.HibernateUtil;
 import org.gnome.yarrr.tests.TestInitializer;
 import org.gnome.yarrr.xmlrpc.DefaultMethods;
+import org.gnome.yarrr.xmlrpc.EmailMethods;
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.tool.hbm2ddl.SchemaUpdate;
 
 
 /*
@@ -81,9 +83,12 @@
     
     public void startXmlRpcServer() {
     	DefaultMethods rpcMessageStore;
+    	EmailMethods rpcEmail;
     	try {
     		Yarrr.rpcServer = StandaloneXmlRpcServer.getXmlRpcServer(19842);
     		rpcMessageStore = new DefaultMethods(this);
+    		rpcEmail = new EmailMethods(this);
+    		Yarrr.rpcServer.shareObject("email", rpcEmail);
     		Yarrr.rpcServer.shareObject("$default", rpcMessageStore);
     	} catch (Exception e) {
     		e.printStackTrace();
Index: src/org/gnome/yarrr/database/PostgresqlManager.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/database/PostgresqlManager.java,v
retrieving revision 1.4
diff -u -r1.4 PostgresqlManager.java
--- src/org/gnome/yarrr/database/PostgresqlManager.java	4 Mar 2005 19:59:13 -0000	1.4
+++ src/org/gnome/yarrr/database/PostgresqlManager.java	12 Mar 2005 00:12:06 -0000
@@ -25,6 +25,7 @@
 import java.util.Random;
 
 import org.apache.log4j.Logger;
+import org.gnome.yarrr.utils.OutputInputStream;
 
 /**
  * Manages an instance of the PostgreSQL server pointing at a custom
@@ -227,35 +228,6 @@
 
 	}
 	
-	class OutputInputStream extends java.lang.Thread {
-		private InputStream in;
-		private OutputStream out;
-		
-		OutputInputStream(String name, InputStream in, OutputStream out) {
-			super(name);
-			this.in = in;
-			this.out = out;
-		}
-
-		public void run() {
-			byte buf[] = new byte[128];
-			int len;
-			try {
-				boolean doneReading = false;
-				while (!doneReading) {
-					len = this.in.read(buf);
-					if (len < 0) {
-						doneReading = true;
-					} else {
-						this.out.write(buf, 0, len);
-					}
-				}
-			} catch (IOException e) {
-				
-			}
-		}
-	}
-
 	/**
 	 * @return a singleton
 	 */
@@ -273,7 +245,7 @@
 		return new PrintStream(fos);
 	}
 	
-	private int execOutput(String cmd) throws IOException {
+	int execOutput(String cmd) throws IOException {
 		logger.debug("Running '" + cmd + "'");
 		
 		// TODO This is what we want to do, but classpath doesn't have getenv();
Index: src/org/gnome/yarrr/email/Email.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/email/Email.java,v
retrieving revision 1.2
diff -u -r1.2 Email.java
--- src/org/gnome/yarrr/email/Email.java	3 Mar 2005 22:14:16 -0000	1.2
+++ src/org/gnome/yarrr/email/Email.java	12 Mar 2005 00:12:06 -0000
@@ -24,8 +24,6 @@
 /**
  * @author dmalcolm
  *
- * TODO To change the template for this generated type comment go to
- * Window - Preferences - Java - Code Style - Code Templates
  */
 public class Email extends Persistent {
     private byte[] rawData; // persists
Index: src/org/gnome/yarrr/email/EmailMessage.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/email/EmailMessage.java,v
retrieving revision 1.3
diff -u -r1.3 EmailMessage.java
--- src/org/gnome/yarrr/email/EmailMessage.java	9 Mar 2005 15:21:40 -0000	1.3
+++ src/org/gnome/yarrr/email/EmailMessage.java	12 Mar 2005 00:12:06 -0000
@@ -10,7 +10,6 @@
 
 import org.gnome.yarrr.Document;
 import org.gnome.yarrr.Message;
-import org.gnome.yarrr.Topic;
 import org.gnome.yarrr.hibernate.HibernateUtil;
 import org.gnome.yarrr.person.Person;
 import org.hibernate.HibernateException;
@@ -43,11 +42,9 @@
      * @param document
      * @throws HibernateException
      */
-    public EmailMessage(Timestamp sentTime, Person author, String subject, Long replyToId, Document document, Topic topic, Email sourceEmail) throws HibernateException {
-        super(sentTime, author, subject, replyToId, document, topic, false);        
+    public EmailMessage(Timestamp sentTime, Person author, String subject, Long replyToId, Document document, Email sourceEmail) throws HibernateException {
+        super(sentTime, author, subject, replyToId, document);        
         this.sourceEmail = sourceEmail;
-        
-        HibernateUtil.getSession().save(this);
     }
     
     public static EmailMessage getByEmailId(String emailId) throws HibernateException {
Index: src/org/gnome/yarrr/email/Importer.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/email/Importer.java,v
retrieving revision 1.3
diff -u -r1.3 Importer.java
--- src/org/gnome/yarrr/email/Importer.java	9 Mar 2005 15:21:40 -0000	1.3
+++ src/org/gnome/yarrr/email/Importer.java	12 Mar 2005 00:12:06 -0000
@@ -16,7 +16,10 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import javax.mail.Address;
 import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeMessage;
 
@@ -53,25 +56,32 @@
         }
     }
     
-    public Person getAuthorForInjectedMail(MimeMessage mimeMessage) throws NoSuchAlgorithmException, NoSuchProviderException{
-        // TODO: Message instances require an author public key
-        // Exactly how should this be implemented?  Dunno, so for now 
-        // just generate a new keypair for each message we inject (!)
-        // Ultimately we might want to be able to identify people in some smart fashion...
-        // signed emails?  or heuristics?
-        // Depends on how I can best wind up Seth (or Havoc)
-        KeyPair pair = Cryptography.generateKeyPair();
-        return Person.getPerson(pair.getPublic());
+    static String getFrom(MimeMessage mimeMessage) throws MessagingException {
+        Address[] addresses = mimeMessage.getFrom();        
+        InternetAddress iaddr = (InternetAddress)addresses[0];
+        return iaddr.getAddress();        
     }
     
-    public Topic getTopicForInjectedMail(MimeMessage mimeMessage, EmailMessage parentEmailMessage) throws HibernateException, MessagingException {
+    public Person getAuthorForInjectedMail(MimeMessage mimeMessage) throws NoSuchAlgorithmException, NoSuchProviderException, MessagingException, HibernateException{
+        String senderAddress = getFrom(mimeMessage);
+        
+        EmailAddress emailAddress = EmailAddress.lookup(senderAddress);
+        if (emailAddress==null) {
+            // create new instance of email
+            KeyPair pair = Cryptography.generateKeyPair();
+            emailAddress = new EmailAddress(senderAddress, pair);
+        }
+        
+        return emailAddress.getPerson();
+    }
+    
+    public Topic getTopicForInjectedMail(MimeMessage mimeMessage, EmailMessage parentEmailMessage, Person mailAuthor) throws HibernateException, MessagingException {
     
         if (parentEmailMessage!=null) {
             // insert into the same topics of the parent email (allowing you to reparent a thread):
             return parentEmailMessage.getTopic();
         }
-        
-        
+            
         // Otherwise, sniff the mailing list:
         List result = new LinkedList();
         
@@ -80,25 +90,38 @@
         if (address!=null) {
             // Email is from a mailing list; lazily create a topic
             MailingList list = MailingList.getMailingList(address.getAddress());
-            
-            if (list!=null) {
-                Topic listTopic = list.getTopic();
-            
-                // Simply use the list topic:
-                return listTopic;
-            }
+            if (list == null && mailAuthor != null)
+            	list = new MailingList(new Topic(mimeMessage.getSubject(), mailAuthor), address.toString());
+            else if (list != null)
+            	return list.getTopic();
         }        
         
+        if (mailAuthor != null)
+        	return new Topic(mimeMessage.getSubject(), mailAuthor);
         return null;
     }
+    
     public String createHtmlForInjectedEmail(MimeMessage mimeMessage) throws MessagingException, IOException {
         HtmlWriter writer = new HtmlWriter();
         return writer.createHtml(mimeMessage);
     }
     
+    private void recursivelyGrabText(Part part, StringBuffer buf) throws MessagingException, IOException {
+    	   Object content = part.getContent();
+           if (content instanceof Multipart) {
+           		Multipart partmulti = (Multipart) content;
+           		for (int i = 0; i < partmulti.getCount(); i++) {
+           			recursivelyGrabText(partmulti.getBodyPart(i), buf);
+           		}
+           } else if (part.getContentType().startsWith("text/plain")) {
+           		buf.append(part.getContent().toString());
+           }
+    }
+    
     public Document createDocumentForInjectedEmail(MimeMessage mimeMessage) throws HibernateException, MessagingException, IOException {
-        String htmlFragment = createHtmlForInjectedEmail(mimeMessage);
-        return Document.createDocument(htmlFragment);
+    	StringBuffer buf = new StringBuffer();
+    	recursivelyGrabText(mimeMessage, buf);
+        return Document.createDocument(buf.toString());
     }
 
     private Timestamp getTimestampForInjectedEmail(MimeMessage mimeMessage) throws MessagingException {
@@ -111,10 +134,7 @@
         }
     }
 
-    /**
-     * TODO: which user? generate a key on startup to a file?
-     */
-    public InjectionResult injectEmail(byte [] rawData) throws Exception {        
+    public InjectionResult injectEmail(byte [] rawData, boolean force) throws Exception {        
         Email injectedEmail;
         List messageInsertions = new LinkedList();
 
@@ -128,7 +148,12 @@
             HibernateUtil.closeSession();            
         }        
 
-        recursivelyMessagifyEmails(injectedEmail, messageInsertions);
+        if (force) {
+        	EmailMessageInsertion insertion = makeMessageFromEmail(injectedEmail, true);
+            messageInsertions.add(insertion);
+        } else {
+        	recursivelyMessagifyEmails(injectedEmail, messageInsertions);
+        }
             
         InjectionResult result = new InjectionResult(injectedEmail, messageInsertions);            
         return result;            
@@ -136,14 +161,15 @@
     
     public void recursivelyMessagifyEmails(Email email, List messageInsertions) throws HibernateException, MessagingException, IOException, NoSuchProviderException, IOException, NoSuchAlgorithmException {
         if (email.shouldHaveMessage()) {            
-            EmailMessageInsertion insertion = makeMessageFromEmail(email);
+            EmailMessageInsertion insertion = makeMessageFromEmail(email, false);
             messageInsertions.add(insertion);
+            logger.info("Email " + email.getSubject() + " should be a message");
             
             // Now repeatedly locate the Email instances which can have EmailMessages generated for them, and generate them:
             // (and repeat, since this may allow other emails to become messagifiable)           
             List unmessagified = Email.getMessagifiableChildren(email);
             for (Iterator i=unmessagified.iterator(); i.hasNext(); ) {
-                Email candidateEmail = (Email)i.next();                
+                Email candidateEmail = (Email)i.next();        
                 recursivelyMessagifyEmails(candidateEmail, messageInsertions);            
             }
         }
@@ -157,7 +183,7 @@
      * @throws NoSuchAlgorithmException 
      * @throws IOException 
      */
-    private EmailMessageInsertion makeMessageFromEmail(Email email) throws HibernateException, MessagingException, NoSuchAlgorithmException, NoSuchProviderException, IOException {
+    private EmailMessageInsertion makeMessageFromEmail(Email email, boolean force) throws HibernateException, MessagingException, NoSuchAlgorithmException, NoSuchProviderException, IOException {
         EmailMessage emailMessage;
         Topic topic;
         try {
@@ -168,7 +194,6 @@
             
             if (parentEmailId!=null) {
                 parentEmailMessage = EmailMessage.getByEmailId(parentEmailId);
-                assert parentEmailMessage!=null;
             }
             
             MimeMessage mimeMessage = email.getMimeMessage();
@@ -177,7 +202,10 @@
             Person author = getAuthorForInjectedMail(mimeMessage);
             
             // Determine which topic(s) to put the email in:
-            topic = getTopicForInjectedMail(mimeMessage, parentEmailMessage);
+            if (force)
+            	topic = getTopicForInjectedMail(mimeMessage, parentEmailMessage, author);
+            else
+            	topic = getTopicForInjectedMail(mimeMessage, parentEmailMessage, null);
             
             Document doc = createDocumentForInjectedEmail(mimeMessage);
             Timestamp timestamp = getTimestampForInjectedEmail(mimeMessage);
@@ -185,20 +213,14 @@
             
             // Set up message threading based on email threading:
             Long replyTo = null;
-            if (parentEmailId!=null) {
-                assert parentEmailMessage!=null;
+            if (parentEmailMessage != null) {
                 replyTo = parentEmailMessage.getId();
             }
 
-            emailMessage = new EmailMessage(null, author, subject, replyTo, doc, topic, email);
+            emailMessage = new EmailMessage(null, author, subject, replyTo, doc, email);
             email.setCreatedMessage(emailMessage);
             
-            // Ensure changes to email make it to the database:
-            // TODO: should this be here?
-            HibernateUtil.getSession().update(email);
-            if (emailMessage!=null) {
-                HibernateUtil.getSession().update(emailMessage);
-            }
+            topic.postMessageUnlocked(emailMessage);
             
             HibernateUtil.commitTransaction();            
             
Index: src/org/gnome/yarrr/email/MailingListSniffer.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/email/MailingListSniffer.java,v
retrieving revision 1.1
diff -u -r1.1 MailingListSniffer.java
--- src/org/gnome/yarrr/email/MailingListSniffer.java	9 Feb 2005 23:22:25 -0000	1.1
+++ src/org/gnome/yarrr/email/MailingListSniffer.java	12 Mar 2005 00:12:06 -0000
@@ -27,7 +27,9 @@
 
         public String matchMessage(MimeMessage mimeMessage) throws MessagingException {
             String[] headerValues = mimeMessage.getHeader(headerName);
-            
+            if (headerValues==null) {
+                return null;
+            }
             for (int i=0;i<headerValues.length;i++) {
                 Matcher matcher = pattern.matcher(headerValues[i]);
                 if (matcher.find()) {
Index: src/org/gnome/yarrr/hibernate/HibernateUtil.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/hibernate/HibernateUtil.java,v
retrieving revision 1.14
diff -u -r1.14 HibernateUtil.java
--- src/org/gnome/yarrr/hibernate/HibernateUtil.java	9 Mar 2005 15:21:39 -0000	1.14
+++ src/org/gnome/yarrr/hibernate/HibernateUtil.java	12 Mar 2005 00:12:06 -0000
@@ -7,6 +7,7 @@
 import org.gnome.yarrr.Topic;
 import org.gnome.yarrr.TopicPerUser;
 import org.gnome.yarrr.email.Email;
+import org.gnome.yarrr.email.EmailAddress;
 import org.gnome.yarrr.email.MailingList;
 import org.gnome.yarrr.person.Group;
 import org.gnome.yarrr.person.Person;
@@ -44,6 +45,7 @@
 		.addClass(Topic.class)
 		.addClass(TopicPerUser.class)
 		.addClass(Email.class)
+        .addClass(EmailAddress.class)
 		.addClass(MailingList.class)
 		.setProperty(Environment.HBM2DDL_AUTO, "update")
 		;
Index: src/org/gnome/yarrr/hibernate/hibernate.properties
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/hibernate/hibernate.properties,v
retrieving revision 1.4
diff -u -r1.4 hibernate.properties
--- src/org/gnome/yarrr/hibernate/hibernate.properties	3 Mar 2005 22:14:16 -0000	1.4
+++ src/org/gnome/yarrr/hibernate/hibernate.properties	12 Mar 2005 00:12:06 -0000
@@ -283,7 +283,7 @@
 
 ## print all generated SQL to the console
 
-hibernate.show_sql false
+hibernate.show_sql true
 
 
 ## auto schema export
Index: src/org/gnome/yarrr/tests/EmailTests.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/tests/EmailTests.java,v
retrieving revision 1.3
diff -u -r1.3 EmailTests.java
--- src/org/gnome/yarrr/tests/EmailTests.java	10 Feb 2005 03:37:55 -0000	1.3
+++ src/org/gnome/yarrr/tests/EmailTests.java	12 Mar 2005 00:12:06 -0000
@@ -4,7 +4,6 @@
  */
 package org.gnome.yarrr.tests;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
@@ -13,27 +12,17 @@
 import javax.mail.Session;
 import javax.mail.internet.MimeMessage;
 
+import org.gnome.yarrr.utils.StreamUtils;
+
 import junit.framework.TestCase;
 
 /**
  * @author dmalcolm
  */
 public class EmailTests extends TestCase {
-    static byte [] loadAllOfStreamJavaDamnYou(InputStream input) throws IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        byte [] buf = new byte[8192];
-        int len;
-        
-        while ((len = input.read(buf)) != -1) {
-            out.write(buf);
-        }
-        return out.toByteArray();
-    }
-    
-    
     static byte [] getTestEmail(String filename) throws IOException {
         InputStream inputStream = EmailTests.class.getResourceAsStream("test-emails/"+filename);
-        return loadAllOfStreamJavaDamnYou(inputStream);
+        return StreamUtils.loadAsByteArray(inputStream);
     }
     
     static public MimeMessage loadTestEmail(String filename) throws MessagingException, IOException {
@@ -52,5 +41,6 @@
         MimeMessage message = loadTestEmail("multiline-subject.email");        
         // FIXME: should it strip out the \r\n\t from the email Subject?  is this a bug in the javamail implementation?
         assertEquals("British English (was Re: GNOME Lovers Needed: l10n work for\r\n\tlocations database)", message.getSubject());        
-    }
+    }    
 }
+
Index: src/org/gnome/yarrr/tests/MailingListTests.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/tests/MailingListTests.java,v
retrieving revision 1.4
diff -u -r1.4 MailingListTests.java
--- src/org/gnome/yarrr/tests/MailingListTests.java	9 Mar 2005 15:21:39 -0000	1.4
+++ src/org/gnome/yarrr/tests/MailingListTests.java	12 Mar 2005 00:12:06 -0000
@@ -4,6 +4,7 @@
  */
 package org.gnome.yarrr.tests;
 
+import java.util.Iterator;
 import java.util.List;
 
 import javax.mail.internet.InternetAddress;
@@ -28,6 +29,32 @@
     private static final String TEST_ML_ADDRESS1 = "mutiny-announce avast me hearties co uk";
     private static final String TEST_ML_ADDRESS2 = "automated-translation spanish-main function";
     
+    public void testInjectForce() throws Exception {
+    	byte[] rawData = EmailTests.getTestEmail("multiline-subject.email");
+        long emailID;
+        
+        Importer importer = new Importer();
+        InjectionResult injectionResult = importer.injectEmail(rawData, true);
+        Email email = (Email)injectionResult.email;
+        Iterator i = injectionResult.messageInsertions.iterator();
+        Importer.EmailMessageInsertion insertion = (Importer.EmailMessageInsertion) i.next();
+        Topic topic = insertion.topic;
+ 
+        emailID = email.getId().longValue();
+        
+        // Sanity test on the email:
+        assertEquals(email.getRawData(), rawData);
+
+        HibernateUtil.newTestTransaction();
+        
+        Email queriedEmail = (Email)Email.getEmail(emailID);
+            
+        assertEquals(rawData.length, queriedEmail.getRawData().length);
+        assertEquals(rawData[56], queriedEmail.getRawData()[56]);
+        
+        assert(topic.containsMessage(queriedEmail.getCreatedMessage()));
+    }
+    
     public void testMailingList() throws Exception {
         long topicID1;
         long topicID2;
@@ -87,7 +114,7 @@
         MimeMessage mimeMessage = EmailTests.loadTestEmail("multiline-subject.email");
         Importer importer = new Importer();
         // Haven't yet registered desktop-devel-list gnome org, so don't know where to put it: 
-        assertNull(importer.getTopicForInjectedMail(mimeMessage, null));
+        assertNull(importer.getTopicForInjectedMail(mimeMessage, null, null));
         
         MailingListSniffer sniffer = new MailingListSniffer();
         InternetAddress address = sniffer.getMailingListAddress(mimeMessage);
@@ -96,7 +123,7 @@
         Topic createdTopic = TestUtils.makeTestTopic("desktop-devel-list", firstMate, "This is where the action is.  Or is it?", null);
         MailingList list1 = new MailingList(createdTopic, address.getAddress());
         
-        Topic queriedTopic = importer.getTopicForInjectedMail(mimeMessage, null);
+        Topic queriedTopic = importer.getTopicForInjectedMail(mimeMessage, null, null);
         
         // Email ought to be put into the topic we just created:
         assertEquals(createdTopic, queriedTopic);
@@ -116,7 +143,7 @@
         MailingList list1 = new MailingList(createdTopic, address.getAddress());
         
         Importer importer = new Importer();
-        InjectionResult injectionResult = importer.injectEmail(rawData);
+        InjectionResult injectionResult = importer.injectEmail(rawData, false);
         Email email = (Email)injectionResult.email;
         
         emailID = email.getId().longValue();
@@ -144,18 +171,18 @@
     	HibernateUtil.newTestTransaction();
     	
     	Importer importer = new Importer();
-    	InjectionResult result1 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1.email"));
+    	InjectionResult result1 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1.email"), false);
     	checkInjectionResult(result1, 1, TEST_THREADING_1_EMAIL_ID, null);
     	
-    	InjectionResult result11 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-1.email"));
+    	InjectionResult result11 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-1.email"), false);
     	checkInjectionResult(result11, 1, TEST_THREADING_1_1_EMAIL_ID, TEST_THREADING_1_EMAIL_ID);
     	assertNotNull(result11.email.getCreatedMessage());
     	
-    	InjectionResult result12 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2.email"));
+    	InjectionResult result12 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2.email"), false);
     	checkInjectionResult(result12, 1, TEST_THREADING_1_2_EMAIL_ID, TEST_THREADING_1_EMAIL_ID);
     	assertNotNull(result12.email.getCreatedMessage());
     	
-    	InjectionResult result121 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2-1.email"));
+    	InjectionResult result121 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2-1.email"), false);
     	checkInjectionResult(result121, 1, TEST_THREADING_1_2_1_EMAIL_ID, TEST_THREADING_1_2_EMAIL_ID);
     	assertNotNull(result121.email.getCreatedMessage());
     	
@@ -181,7 +208,7 @@
     	HibernateUtil.newTestTransaction();            
     	
     	Importer importer = new Importer();
-    	InjectionResult result121 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2-1.email"));
+    	InjectionResult result121 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2-1.email"), false);
     	checkInjectionResult(result121, 0, TEST_THREADING_1_2_1_EMAIL_ID, TEST_THREADING_1_2_EMAIL_ID);
     	assertNull(result121.email.getCreatedMessage());
     	assertEquals(TEST_THREADING_1_2_1_EMAIL_ID, result121.email.getEmailId());
@@ -190,17 +217,17 @@
     	// grrr.. this isn't finding the message for some reason
     	assertEquals(1, Email.getMessagifiableChildren(TEST_THREADING_1_2_EMAIL_ID).size());
     	
-    	InjectionResult result12 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2.email"));
+    	InjectionResult result12 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-2.email"), false);
     	checkInjectionResult(result12, 0, TEST_THREADING_1_2_EMAIL_ID, TEST_THREADING_1_EMAIL_ID);
     	assertNull(result12.email.getCreatedMessage());
     	assertEquals(1, Email.getMessagifiableChildren(TEST_THREADING_1_EMAIL_ID).size());
     	
-    	InjectionResult result11 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-1.email"));
+    	InjectionResult result11 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1-1.email"), false);
     	checkInjectionResult(result11, 0, TEST_THREADING_1_1_EMAIL_ID, TEST_THREADING_1_EMAIL_ID);
     	assertNull(result11.email.getCreatedMessage());
     	assertEquals(2, Email.getMessagifiableChildren(TEST_THREADING_1_EMAIL_ID).size());
     	
-    	InjectionResult result1 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1.email"));
+    	InjectionResult result1 = importer.injectEmail(EmailTests.getTestEmail("test-threading-1.email"), false);
     	
     	assertNotNull(result1.email.getCreatedMessage());
     	checkInjectionResult(result1, 4, TEST_THREADING_1_EMAIL_ID, null);
Index: src/org/gnome/yarrr/tests/TestInitializerTests.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/tests/TestInitializerTests.java,v
retrieving revision 1.7
diff -u -r1.7 TestInitializerTests.java
--- src/org/gnome/yarrr/tests/TestInitializerTests.java	9 Mar 2005 15:21:38 -0000	1.7
+++ src/org/gnome/yarrr/tests/TestInitializerTests.java	12 Mar 2005 00:12:06 -0000
@@ -23,7 +23,7 @@
         init.doCreation();
         
         List topics = Topic.getAllTopics();        
-        assertEquals(10,topics.size());
+        assertEquals(6,topics.size());
         
         for (Iterator i=topics.iterator(); i.hasNext(); ) {
             Topic topic = (Topic)i.next();
Index: src/org/gnome/yarrr/xmlrpc/DefaultMethods.java
===================================================================
RCS file: /cvs/gnome/yarrr/src/org/gnome/yarrr/xmlrpc/DefaultMethods.java,v
retrieving revision 1.24
diff -u -r1.24 DefaultMethods.java
--- src/org/gnome/yarrr/xmlrpc/DefaultMethods.java	11 Mar 2005 10:43:32 -0000	1.24
+++ src/org/gnome/yarrr/xmlrpc/DefaultMethods.java	12 Mar 2005 00:12:06 -0000
@@ -3,9 +3,7 @@
  */
 package org.gnome.yarrr.xmlrpc;
 
-import java.math.BigInteger;
 import java.security.KeyPair;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
 import java.util.Collection;
@@ -19,8 +17,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.xmlrpc.Invoker;
-import org.apache.xmlrpc.XmlRpcHandler;
 import org.gnome.yarrr.Cryptography;
 import org.gnome.yarrr.Document;
 import org.gnome.yarrr.Message;
@@ -29,15 +25,12 @@
 import org.gnome.yarrr.Topic;
 import org.gnome.yarrr.TopicPerUser;
 import org.gnome.yarrr.Yarrr;
-import org.gnome.yarrr.email.Importer;
-import org.gnome.yarrr.email.Importer.InjectionResult;
-import org.gnome.yarrr.hibernate.HibernateUtil;
 import org.gnome.yarrr.person.Person;
 
 /**
  * @author seth
  */
-public class DefaultMethods implements XmlRpcHandler {
+public class DefaultMethods extends YarrrRPCHandler {
 
 	static Log logger = LogFactory.getLog(DefaultMethods.class);
 	
@@ -143,27 +136,7 @@
 		
 		return target.getId().toString();
 	}
-	
-    public String injectEmail(byte [] contents) throws Exception {
-    	Importer importer = new Importer();
-        InjectionResult injectionResult = importer.injectEmail(contents);
-        String stringResult = "avast! added email:\""+injectionResult.email.getMimeMessage().getSubject()+"\"\n";
-        
-        for (Iterator i = injectionResult.messageInsertions.iterator(); i.hasNext();) {
-            Importer.EmailMessageInsertion insertion = (Importer.EmailMessageInsertion)i.next();
-        
-            stringResult += "added message:\""+insertion.emailMessage.getSubject()+"\"";
-            if (insertion.topic != null) {
-                stringResult += " to topic \"" + insertion.topic.getName() + "\" ";;
-            } else {
-                stringResult += " to database (not added to any topics)";
-            }        
-        }
-        logger.info(stringResult);
 
-        return stringResult;
-    }
-	
 	public Vector updateTopic(String topicId, byte[] userPublicKeyBytes, String versionAtClientString, String perUserVersionAtClientString) throws Exception {
 		long versionAtClient = new Long(versionAtClientString).longValue();
 		long perUserVersionAtClient = new Long(perUserVersionAtClientString).longValue();
@@ -370,65 +343,7 @@
 		return result;
 	}
 	
-	/* Functions for managing the XML-RPC interface, not calls */
-	
-	private String parameterAsString(Object o) throws NoSuchAlgorithmException {
-		String oString = o.toString();
-		
-		// Special case public keys:
-		try {
-			// Try to convert to byte array
-			byte [] bytes = (byte [])o;
-			// Try to convert it to a public key
-			PublicKey publicKey = Cryptography.bytesToPublicKey(bytes);
-			// It succeeded, lets make a digest of it to display
-			byte[] digest = MessageDigest.getInstance("SHA-1").digest(bytes);
-			String digeststr = new BigInteger(digest).abs().toString(16);
-			oString = "[SHA-1:" + digeststr + "]";
-		} catch (Cryptography.EncryptionException e) {
-			// Wasn't a key
-		} catch (ClassCastException e) {
-			// Wasn't a byte[]
-		} 
-		
-		return oString;
-	}
-	
-	/**
-	 * Called in order to invoke any methods of this class. Performs
-	 * introspection, and pre-processes a few arguments.
-	 * 
-	 * @see XmlRpcHandler.execute
-	 */
-	public Object execute(String methodName, Vector params) throws Exception {
-		try {
-			HibernateUtil.beginTransaction();
-			
-			if (logger.isInfoEnabled()) {
-				logger.info("invoking xmlRpc method " + methodName + "() with " + params.size()  +" arguments:");
-				Iterator i;	int n;
-				for (n = 1, i = params.iterator(); i.hasNext(); n++) {
-					Object o = i.next();
-					logger.info(n +": " + o.getClass().getName() + " = " + parameterAsString(o));
-				}
-			}
-			
-			Object res = this.invoker.execute(methodName, params);
-			HibernateUtil.commitTransaction();
-			return res;
-		} catch (Exception e) {
-			logger.error("XML-RPC failure", e);
-			throw e;
-		} finally {
-			HibernateUtil.closeSession();
-		}
-	}
-	
-	private Yarrr yarrr;
-	private Invoker invoker;
-	
 	public DefaultMethods (Yarrr yarrr) throws NoSuchAlgorithmException {
-		this.invoker = new Invoker(this);
-		this.yarrr = yarrr;
+		super(yarrr);
 	}
 }
Index: tools/pressgang.py
===================================================================
RCS file: /cvs/gnome/yarrr/tools/pressgang.py,v
retrieving revision 1.2
diff -u -r1.2 pressgang.py
--- tools/pressgang.py	6 Feb 2005 05:39:18 -0000	1.2
+++ tools/pressgang.py	12 Mar 2005 00:12:06 -0000
@@ -3,9 +3,13 @@
 
 if __name__ == '__main__':
     if len(sys.argv) < 2:
-        print "Usage: pressgang.py http://SERVER-NAME:SERVER-PORT (email-file)"
+        print "Usage: pressgang.py http://SERVER-NAME:SERVER-PORT (email-file) (force)"
         
     servername = sys.argv[1]
+    if len(sys.argv) > 2:
+    	force = True
+    else:
+    	force = False
 
     server = xmlrpclib.Server(servername)
 
@@ -13,6 +17,6 @@
         content = sys.stdin.read()
     else:
         content = file(sys.argv[2]).read()
-    print server.yarrr.injectEmail (xmlrpclib.Binary (content))
+    print server.email.injectEmail (xmlrpclib.Binary (content), force)
 
 
Index: src/org/gnome/yarrr/email/EmailAddress.hbm.xml
===================================================================
RCS file: src/org/gnome/yarrr/email/EmailAddress.hbm.xml
diff -N src/org/gnome/yarrr/email/EmailAddress.hbm.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/email/EmailAddress.hbm.xml	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd";>
+<hibernate-mapping 
+	package="org.gnome.yarrr.email">
+
+	<class name="EmailAddress">
+		<id name="id">
+			<generator class="native"/>
+		</id>
+		<property name="address"/>
+		<property name="keypair"/>
+	</class>
+	
+</hibernate-mapping>
Index: src/org/gnome/yarrr/email/EmailAddress.java
===================================================================
RCS file: src/org/gnome/yarrr/email/EmailAddress.java
diff -N src/org/gnome/yarrr/email/EmailAddress.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/email/EmailAddress.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,69 @@
+/*
+ * Created on 07-Mar-2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.email;
+
+import java.security.KeyPair;
+
+import org.gnome.yarrr.hibernate.HibernateUtil;
+import org.gnome.yarrr.hibernate.Persistent;
+import org.gnome.yarrr.person.Person;
+import org.hibernate.HibernateException;
+import org.hibernate.criterion.Expression;
+
+/**
+ * @author dmalcolm
+ *
+ * Class representing an email address, when handling email feeds.
+ * We autogenerate a keypair/person to cover each email address we encounter, since all we can say about these messages
+ * is that they appear to come from a particular email address (and relatively few people sign their messages).
+ */
+public class EmailAddress extends Persistent {
+    String address;
+    KeyPair keypair;
+    
+    protected EmailAddress() {
+    }
+    
+    public EmailAddress(String address, KeyPair keypair) throws HibernateException {
+        this.address = address;
+        this.keypair = keypair;
+        HibernateUtil.getSession().save(this);
+    }
+    
+    public String getAddress() {
+        return address;
+    }
+    public void setAddress(String address) {
+        this.address = address;
+    }
+    public KeyPair getKeypair() {
+        return keypair;
+    }
+    public void setKeypair(KeyPair keypair) {
+        this.keypair = keypair;
+    }
+
+    /**
+     * @param senderAddress
+     * @return
+     * @throws HibernateException 
+     */
+    public static EmailAddress lookup(String stringAddress) throws HibernateException {
+        EmailAddress result = (EmailAddress)
+            HibernateUtil.getSession().createCriteria(EmailAddress.class)
+                .add( Expression.eq("address", stringAddress) )
+                .uniqueResult();
+        return result;
+    }
+
+    /**
+     * @return
+     */
+    public Person getPerson() {
+        return Person.getPerson(keypair.getPublic());
+    }
+}
Index: src/org/gnome/yarrr/tests/StreamUtilTests.java
===================================================================
RCS file: src/org/gnome/yarrr/tests/StreamUtilTests.java
diff -N src/org/gnome/yarrr/tests/StreamUtilTests.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/tests/StreamUtilTests.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,55 @@
+/*
+ * Created on 03-Mar-2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.tests;
+
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+import org.gnome.yarrr.utils.StreamUtils;
+
+/**
+ * @author dmalcolm
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class StreamUtilTests extends TestCase {
+    private static final String TXT_GZ_URL = "http://mail.gnome.org/archives/desktop-devel-list/2003-August.txt.gz";;
+    
+    public void testLoadLocalFile() throws Exception {
+        InputStream inputStream = EmailTests.class.getResourceAsStream("test-emails/multiline-subject.email");
+        byte[] byteArray = StreamUtils.loadAsByteArray(inputStream);
+        assertEquals(5119, byteArray.length);
+    }
+    
+//    public void testLoadRemoteFile() throws Exception {
+//        URL url = new URL(TXT_GZ_URL);   
+//        InputStream in = url.openStream();
+//        
+//        byte[] byteArray = StreamUtils.loadAsByteArray(in);
+//        assertEquals(996100, byteArray.length);        
+//    }
+//
+//    public void testLoadRemoteInflateFile() throws Exception {
+//        URL url = new URL(TXT_GZ_URL);
+//        
+//        // appears to be DEFLATE data format:
+//        InputStream in = new InflaterInputStream(url.openStream());        
+//        byte[] byteArray = StreamUtils.loadAsByteArray(in);        
+//        assertEquals(3087158, byteArray.length);       
+//        
+//    }
+    
+//    public void testLoadRemoteGzipFile() throws Exception {
+//        URL url = new URL(TXT_GZ_URL);
+//        
+//        InputStream in = url.openStream();        
+//        byte[] byteArray = StreamUtils.loadAsGZippedByteArray(in);
+//        assertEquals(3087158, byteArray.length);        
+//    }
+}
Index: src/org/gnome/yarrr/utils/OutputInputStream.java
===================================================================
RCS file: src/org/gnome/yarrr/utils/OutputInputStream.java
diff -N src/org/gnome/yarrr/utils/OutputInputStream.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/utils/OutputInputStream.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,41 @@
+/*
+ * Created on 03-Mar-2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+public class OutputInputStream extends java.lang.Thread {
+	InputStream in;
+	OutputStream out;
+	
+	public OutputInputStream(String name, InputStream in, OutputStream out) {
+		super(name);
+		this.in = in;
+		this.out = out;
+	}
+
+	public void run() {
+		byte buf[] = new byte[128];
+		int len;
+		try {
+			boolean doneReading = false;
+			while (!doneReading) {
+				len = this.in.read(buf);
+				if (len < 0) {
+					doneReading = true;
+				} else {
+					this.out.write(buf, 0, len);
+				}
+			}
+		} catch (IOException e) {
+			
+		}
+	}
+}
Index: src/org/gnome/yarrr/utils/StreamUtils.java
===================================================================
RCS file: src/org/gnome/yarrr/utils/StreamUtils.java
diff -N src/org/gnome/yarrr/utils/StreamUtils.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/utils/StreamUtils.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,48 @@
+/*
+ * Created on 03-Mar-2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * @author dmalcolm
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class StreamUtils {
+    static public byte [] loadAsByteArray(InputStream input) throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        byte [] buf = new byte[8192];
+        int len;
+        int offset=0;
+        
+        while ((len = input.read(buf)) != -1) {
+            out.write(buf, 0, len);
+            //offset+=len;
+        }
+        return out.toByteArray();
+    }
+    
+    // For some reason loadAsByteArray(new GZIPInputStream(input)) doesn't work when downloading from a URL
+    // grrr.. only wants to read 2401 bytes...
+    // Do it in two stages instead.
+    static public byte [] loadAsGZippedByteArray(InputStream input) throws IOException {
+        byte[] compressedByteArray = loadAsByteArray(input);
+        
+        InputStream gzipStream = new GZIPInputStream(new ByteArrayInputStream(compressedByteArray));
+        
+        byte[] decompressedByteArray = loadAsByteArray(gzipStream);
+        
+        return decompressedByteArray;
+    }
+    
+}
Index: src/org/gnome/yarrr/xmlrpc/EmailMethods.java
===================================================================
RCS file: src/org/gnome/yarrr/xmlrpc/EmailMethods.java
diff -N src/org/gnome/yarrr/xmlrpc/EmailMethods.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/xmlrpc/EmailMethods.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,49 @@
+/*
+ * Created on Mar 11, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.xmlrpc;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.gnome.yarrr.Yarrr;
+import org.gnome.yarrr.email.Importer;
+import org.gnome.yarrr.email.Importer.InjectionResult;
+
+/**
+ * @author walters
+ */
+public class EmailMethods extends YarrrRPCHandler {
+
+	static Log logger = LogFactory.getLog(DefaultMethods.class);
+	
+	public EmailMethods(Yarrr yarrr) throws NoSuchAlgorithmException {
+		super(yarrr);
+	}
+	
+    public String injectEmail(byte [] contents, boolean force) throws Exception {
+    	Importer importer = new Importer();
+        InjectionResult injectionResult = importer.injectEmail(contents, force);
+        String stringResult = "avast! added email:\""+injectionResult.email.getMimeMessage().getSubject()+"\"\n";
+        
+        for (Iterator i = injectionResult.messageInsertions.iterator(); i.hasNext();) {
+            Importer.EmailMessageInsertion insertion = (Importer.EmailMessageInsertion)i.next();
+        
+            stringResult += "added message:\""+insertion.emailMessage.getSubject()+"\"";
+            if (insertion.topic != null) {
+                stringResult += " to topic \"" + insertion.topic.getName() + " (id " + insertion.topic.getStringId() + ") \" ";;
+            } else {
+                stringResult += " to database (not added to any topics)";
+            }        
+        }
+        logger.info(stringResult);
+
+        return stringResult;
+    }
+
+}
Index: src/org/gnome/yarrr/xmlrpc/YarrrRPCHandler.java
===================================================================
RCS file: src/org/gnome/yarrr/xmlrpc/YarrrRPCHandler.java
diff -N src/org/gnome/yarrr/xmlrpc/YarrrRPCHandler.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/gnome/yarrr/xmlrpc/YarrrRPCHandler.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,87 @@
+/*
+ * Created on Mar 11, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.gnome.yarrr.xmlrpc;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xmlrpc.Invoker;
+import org.apache.xmlrpc.XmlRpcHandler;
+import org.gnome.yarrr.Cryptography;
+import org.gnome.yarrr.Yarrr;
+import org.gnome.yarrr.hibernate.HibernateUtil;
+
+/**
+ * @author walters
+ */
+public class YarrrRPCHandler implements XmlRpcHandler {
+
+	static Log logger = LogFactory.getLog(YarrrRPCHandler.class);
+	
+	protected Yarrr yarrr;
+	protected Invoker invoker;
+	
+	/* Functions for managing the XML-RPC interface, not calls */
+	
+	protected String parameterAsString(Object o) throws NoSuchAlgorithmException {
+		String oString = o.toString();
+		
+		// Special case public keys:
+		try {
+			// Try to convert to byte array
+			byte [] bytes = (byte [])o;
+			// Try to convert it to a public key
+			PublicKey publicKey = Cryptography.bytesToPublicKey(bytes);
+			// It succeeded, lets make a digest of it to display
+			byte[] digest = MessageDigest.getInstance("SHA-1").digest(bytes);
+			String digeststr = new BigInteger(digest).abs().toString(16);
+			oString = "[SHA-1:" + digeststr + "]";
+		} catch (Cryptography.EncryptionException e) {
+			// Wasn't a key
+		} catch (ClassCastException e) {
+			// Wasn't a byte[]
+		} 
+		
+		return oString;
+	}
+	
+	
+	public Object execute(String methodName, Vector params) throws Exception {
+		try {
+			HibernateUtil.beginTransaction();
+			
+			if (logger.isInfoEnabled()) {
+				logger.info("[" + this.getClass().getName() + "] invoking xmlRpc method " + methodName + "() with " + params.size()  +" arguments:");
+				Iterator i;	int n;
+				for (n = 1, i = params.iterator(); i.hasNext(); n++) {
+					Object o = i.next();
+					logger.info(n +": " + o.getClass().getName() + " = " + parameterAsString(o));
+				}
+			}
+			
+			Object res = this.invoker.execute(methodName, params);
+			HibernateUtil.commitTransaction();
+			return res;
+		} catch (Exception e) {
+			logger.error("XML-RPC failure", e);
+			throw e;
+		} finally {
+			HibernateUtil.closeSession();
+		}
+	}
+	
+	public YarrrRPCHandler (Yarrr yarrr) throws NoSuchAlgorithmException {
+		this.invoker = new Invoker(this);
+		this.yarrr = yarrr;
+	}
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]