Removed invitation code from simplex plugins, cleaned up Gmail plugin.

This commit is contained in:
akwizgran
2012-09-26 12:34:37 +01:00
parent 36cd02128c
commit e534722d60
11 changed files with 59 additions and 253 deletions

View File

@@ -35,7 +35,4 @@ public interface Plugin {
* the plugin may exclude the given contacts from polling. * the plugin may exclude the given contacts from polling.
*/ */
void poll(Collection<ContactId> connected); void poll(Collection<ContactId> connected);
/** Returns true if the plugin supports exchanging invitations. */
boolean supportsInvitations();
} }

View File

@@ -3,13 +3,13 @@ package net.sf.briar.api.plugins;
import java.util.Collection; import java.util.Collection;
import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.simplex.SimplexPlugin;
public interface PluginManager { public interface PluginManager {
/** /**
* Starts the plugins and returns the number of plugins successfully * Starts the plugins and returns the number of plugins successfully
* started. * started. This method must not be called until the database has been
* opened.
*/ */
int start(); int start();
@@ -19,8 +19,5 @@ public interface PluginManager {
int stop(); int stop();
/** Returns any duplex plugins that support invitations. */ /** Returns any duplex plugins that support invitations. */
Collection<DuplexPlugin> getDuplexInvitationPlugins(); Collection<DuplexPlugin> getInvitationPlugins();
/** Returns any simplex plugins that support invitations. */
Collection<SimplexPlugin> getSimplexInvitationPlugins();
} }

View File

@@ -14,6 +14,9 @@ public interface DuplexPlugin extends Plugin {
*/ */
DuplexTransportConnection createConnection(ContactId c); DuplexTransportConnection createConnection(ContactId c);
/** Returns true if the plugin supports exchanging invitations. */
boolean supportsInvitations();
/** /**
* Starts the invitation process from the inviter's side. Returns null if * Starts the invitation process from the inviter's side. Returns null if
* no connection can be established within the given timeout. * no connection can be established within the given timeout.

View File

@@ -1,7 +1,6 @@
package net.sf.briar.api.plugins.simplex; package net.sf.briar.api.plugins.simplex;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.plugins.Plugin; import net.sf.briar.api.plugins.Plugin;
/** An interface for transport plugins that support simplex communication. */ /** An interface for transport plugins that support simplex communication. */
@@ -20,29 +19,4 @@ public interface SimplexPlugin extends Plugin {
* could not be created. * could not be created.
*/ */
SimplexTransportWriter createWriter(ContactId c); SimplexTransportWriter createWriter(ContactId c);
/**
* Starts the invitation process from the inviter's side. Returns null if
* no connection can be established within the given timeout.
*/
SimplexTransportWriter sendInvitation(PseudoRandom r, long timeout);
/**
* Starts the invitation process from the invitee's side. Returns null if
* no connection can be established within the given timeout.
*/
SimplexTransportReader acceptInvitation(PseudoRandom r, long timeout);
/**
* Continues the invitation process from the invitee's side. Returns null
* if no connection can be established within the given timeout.
*/
SimplexTransportWriter sendInvitationResponse(PseudoRandom r, long timeout);
/**
* Continues the invitation process from the inviter's side. Returns null
* if no connection can be established within the given timeout.
*/
SimplexTransportReader acceptInvitationResponse(PseudoRandom r,
long timeout);
} }

View File

@@ -73,10 +73,6 @@ class PluginManagerImpl implements PluginManager {
duplexPlugins = new ArrayList<DuplexPlugin>(); duplexPlugins = new ArrayList<DuplexPlugin>();
} }
public synchronized int getPluginCount() {
return simplexPlugins.size() + duplexPlugins.size();
}
public synchronized int start() { public synchronized int start() {
Set<TransportId> ids = new HashSet<TransportId>(); Set<TransportId> ids = new HashSet<TransportId>();
// Instantiate and start the simplex plugins // Instantiate and start the simplex plugins
@@ -184,7 +180,7 @@ class PluginManagerImpl implements PluginManager {
return stopped; return stopped;
} }
public Collection<DuplexPlugin> getDuplexInvitationPlugins() { public Collection<DuplexPlugin> getInvitationPlugins() {
Collection<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); Collection<DuplexPlugin> supported = new ArrayList<DuplexPlugin>();
synchronized(this) { synchronized(this) {
for(DuplexPlugin d : duplexPlugins) { for(DuplexPlugin d : duplexPlugins) {
@@ -194,16 +190,6 @@ class PluginManagerImpl implements PluginManager {
return supported; return supported;
} }
public Collection<SimplexPlugin> getSimplexInvitationPlugins() {
Collection<SimplexPlugin> supported = new ArrayList<SimplexPlugin>();
synchronized(this) {
for(SimplexPlugin s : simplexPlugins) {
if(s.supportsInvitations()) supported.add(s);
}
}
return supported;
}
private abstract class PluginCallbackImpl implements PluginCallback { private abstract class PluginCallbackImpl implements PluginCallback {
protected volatile TransportId id = null; protected volatile TransportId id = null;

View File

@@ -14,6 +14,7 @@ import java.util.logging.Logger;
import javax.activation.DataHandler; import javax.activation.DataHandler;
import javax.activation.DataSource; import javax.activation.DataSource;
import javax.mail.Authenticator;
import javax.mail.Flags; import javax.mail.Flags;
import javax.mail.Flags.Flag; import javax.mail.Flags.Flag;
import javax.mail.Folder; import javax.mail.Folder;
@@ -34,7 +35,6 @@ import javax.mail.util.ByteArrayDataSource;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportConfig;
import net.sf.briar.api.TransportProperties; import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.plugins.simplex.SimplexPlugin; import net.sf.briar.api.plugins.simplex.SimplexPlugin;
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback; import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
import net.sf.briar.api.plugins.simplex.SimplexTransportReader; import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
@@ -42,7 +42,7 @@ import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.util.StringUtils; import net.sf.briar.util.StringUtils;
public class GmailPlugin implements SimplexPlugin { class GmailPlugin implements SimplexPlugin {
public static final byte[] TRANSPORT_ID = StringUtils public static final byte[] TRANSPORT_ID = StringUtils
.fromHexString("57ead1961d2120bbbbe8256ff9ce6ae2" .fromHexString("57ead1961d2120bbbbe8256ff9ce6ae2"
@@ -50,12 +50,11 @@ public class GmailPlugin implements SimplexPlugin {
+ "e8dd928ed1d7a9e7b89fd62210aa30bf"); + "e8dd928ed1d7a9e7b89fd62210aa30bf");
private static final TransportId ID = new TransportId(TRANSPORT_ID); private static final TransportId ID = new TransportId(TRANSPORT_ID);
private static final Logger LOG =
Logger.getLogger(GmailPlugin.class.getName());
private final Executor pluginExecutor; private final Executor pluginExecutor;
private final SimplexPluginCallback callback; private final SimplexPluginCallback callback;
private static final Logger LOG = Logger.getLogger(GmailPlugin.class
.getName());
// private static GmailTransportConnectionWriter writer;
public GmailPlugin(Executor pluginExecutor, SimplexPluginCallback callback) { public GmailPlugin(Executor pluginExecutor, SimplexPluginCallback callback) {
this.pluginExecutor = pluginExecutor; this.pluginExecutor = pluginExecutor;
@@ -78,15 +77,14 @@ public class GmailPlugin implements SimplexPlugin {
try { try {
FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false); FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
Message msg[] = inbox.search(ft); Message msg[] = inbox.search(ft);
// System.out.println("Unread Messages: "+ msg.length); for(final Message message : msg) {
for (final Message message : msg) {
callback.readerCreated(new SimplexTransportReader() { callback.readerCreated(new SimplexTransportReader() {
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
try { try {
return message.getInputStream(); return message.getInputStream();
} catch (MessagingException e) { } catch(MessagingException e) {
if (LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING))
LOG.warning(e.toString()); LOG.warning(e.toString());
} }
return null; return null;
@@ -97,17 +95,15 @@ public class GmailPlugin implements SimplexPlugin {
try { try {
message.setFlag(Flag.DELETED, recognised); message.setFlag(Flag.DELETED, recognised);
message.setFlag(Flag.SEEN, recognised); message.setFlag(Flag.SEEN, recognised);
} catch (MessagingException e) { } catch(MessagingException e) {
if (LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING))
LOG.warning(e.toString()); LOG.warning(e.toString());
} }
} }
}); });
} }
} catch (MessagingException e) { } catch(MessagingException e) {
if (LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
LOG.warning(e.toString());
} }
} }
@@ -116,7 +112,7 @@ public class GmailPlugin implements SimplexPlugin {
props.setProperty("mail.store.protocol", "imaps"); props.setProperty("mail.store.protocol", "imaps");
final ArrayList<String> userPass = getAuthenticationDetails(callback final ArrayList<String> userPass = getAuthenticationDetails(callback
.getConfig()); .getConfig());
if (userPass != null) { if(userPass != null) {
try { try {
Session session = Session.getInstance(props, null); Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps"); Store store = session.getStore("imaps");
@@ -125,19 +121,17 @@ public class GmailPlugin implements SimplexPlugin {
Folder inbox = store.getFolder("Inbox"); Folder inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_ONLY); inbox.open(Folder.READ_ONLY);
checkUnreadEmails(inbox); checkUnreadEmails(inbox);
} catch (NoSuchProviderException e) { } catch(NoSuchProviderException e) {
if (LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
LOG.warning(e.toString()); } catch(MessagingException e) {
} catch (MessagingException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
if (LOG.isLoggable(Level.WARNING))
LOG.warning(e.toString());
} }
} }
} }
public boolean connectSMTP(ContactId cid) { public boolean connectSMTP(ContactId cid) {
boolean sent = false; boolean sent = false;
if (discoverContactEmail(cid) != null) { if(discoverContactEmail(cid) != null) {
Properties props = new Properties(); Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.port", "465");
@@ -146,19 +140,18 @@ public class GmailPlugin implements SimplexPlugin {
props.put("mail.smtp.auth", "true"); props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465"); props.put("mail.smtp.port", "465");
final ArrayList<String> userPass = getAuthenticationDetails(callback final ArrayList<String> userPass =
.getConfig()); getAuthenticationDetails(callback.getConfig());
if (userPass != null) { if(userPass != null) {
Session session; Session session;
session = Session.getInstance(props, session = Session.getInstance(props,
new javax.mail.Authenticator() { new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() { protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userPass return new PasswordAuthentication(
.get(0), userPass.get(1)); userPass.get(0), userPass.get(1));
} }
}); });
sent = sendMessage(session, cid); sent = sendMessage(session, cid);
} }
} }
@@ -166,7 +159,6 @@ public class GmailPlugin implements SimplexPlugin {
} }
private boolean sendMessage(Session session, ContactId cid) { private boolean sendMessage(Session session, ContactId cid) {
boolean sent = false;
ByteArrayOutputStream outputStream = null; ByteArrayOutputStream outputStream = null;
try { try {
Message message = new MimeMessage(session); Message message = new MimeMessage(session);
@@ -187,15 +179,15 @@ public class GmailPlugin implements SimplexPlugin {
} }
public OutputStream getOutputStream() throws IOException { public OutputStream getOutputStream() throws IOException {
return null; return null; // FIXME
} }
public long getCapacity() { public long getCapacity() {
return 0; return 0; // FIXME
} }
public void dispose(boolean exception) throws IOException { public void dispose(boolean exception) throws IOException {
// FIXME
} }
}); });
@@ -211,22 +203,18 @@ public class GmailPlugin implements SimplexPlugin {
message.setContent(mimeMultipart); message.setContent(mimeMultipart);
// message.setText("Test content");
Transport.send(message); Transport.send(message);
sent = true; return true;
return sent; } catch(MessagingException e) {
} catch (MessagingException e) { return false;
return sent;
} finally { } finally {
if (null != outputStream) { if(outputStream != null) {
try { try {
outputStream.close(); outputStream.close();
outputStream = null; outputStream = null;
} catch (Exception e) { } catch(Exception e) {
if (LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
LOG.warning(e.toString());
} }
} }
} }
@@ -234,8 +222,8 @@ public class GmailPlugin implements SimplexPlugin {
} }
public void stop() throws IOException { public void stop() throws IOException {
synchronized (this) { synchronized(this) {
// close open connections // FIXME: Close open connections
} }
} }
@@ -251,10 +239,6 @@ public class GmailPlugin implements SimplexPlugin {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public boolean supportsInvitations() {
return false;
}
/* /*
* Gets the user's authentication details ArrayList.get(0) = username, * Gets the user's authentication details ArrayList.get(0) = username,
* ArrayList.get(1) = password, or null if either value is null. * ArrayList.get(1) = password, or null if either value is null.
@@ -264,31 +248,35 @@ public class GmailPlugin implements SimplexPlugin {
ArrayList<String> usernamePass = new ArrayList<String>(); ArrayList<String> usernamePass = new ArrayList<String>();
usernamePass.add(0, config.get("username")); usernamePass.add(0, config.get("username"));
usernamePass.add(1, config.get("password")); usernamePass.add(1, config.get("password"));
if (usernamePass.get(0) != null && usernamePass.get(1) != null) if(usernamePass.get(0) != null && usernamePass.get(1) != null) {
return usernamePass; return usernamePass;
else } else {
return null; return null;
} catch (Exception e) { }
} catch(Exception e) {
return null; return null;
} }
} }
/* /*
* Looks up the contact's email address given the contactID * Looks up the contact's email address given the contactID
*
* @param ContactId * @param ContactId
*
* @return String email * @return String email
*/ */
private String discoverContactEmail(ContactId cid) { private String discoverContactEmail(ContactId cid) {
try { try {
Map<ContactId, TransportProperties> remote = callback Map<ContactId, TransportProperties> remote =
.getRemoteProperties(); callback.getRemoteProperties();
TransportProperties tp = remote.get(cid); TransportProperties tp = remote.get(cid);
if (tp != null) { if(tp != null) {
String address = tp.get("email"); String address = tp.get("email");
return address; return address;
} else } else {
return null; return null;
} catch (Exception e) { }
} catch(Exception e) {
return null; return null;
} }
} }
@@ -300,23 +288,4 @@ public class GmailPlugin implements SimplexPlugin {
public SimplexTransportWriter createWriter(ContactId c) { public SimplexTransportWriter createWriter(ContactId c) {
return null; return null;
} }
public SimplexTransportWriter sendInvitation(PseudoRandom r, long timeout) {
throw new UnsupportedOperationException();
}
public SimplexTransportReader acceptInvitation(PseudoRandom r, long timeout) {
throw new UnsupportedOperationException();
}
public SimplexTransportWriter sendInvitationResponse(PseudoRandom r,
long timeout) {
throw new UnsupportedOperationException();
}
public SimplexTransportReader acceptInvitationResponse(PseudoRandom r,
long timeout) {
throw new UnsupportedOperationException();
}
} }

View File

@@ -10,9 +10,6 @@ public class GmailPluginFactory implements SimplexPluginFactory {
public SimplexPlugin createPlugin(Executor pluginExecutor, public SimplexPlugin createPlugin(Executor pluginExecutor,
SimplexPluginCallback callback) { SimplexPluginCallback callback) {
return new GmailPlugin(pluginExecutor, callback); return new GmailPlugin(pluginExecutor, callback);
} }
} }

View File

@@ -9,9 +9,10 @@ import javax.microedition.io.StreamConnection;
import net.sf.briar.api.plugins.simplex.SimplexTransportWriter; import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
public class GmailTransportConnectionWriter implements SimplexTransportWriter { class GmailTransportConnectionWriter implements SimplexTransportWriter {
private static final Logger LOG = Logger.getLogger(GmailTransportConnectionWriter.class.getName()); private static final Logger LOG =
Logger.getLogger(GmailTransportConnectionWriter.class.getName());
private final StreamConnection stream; private final StreamConnection stream;
private final long capacity = 25 * 1000 * 1000; private final long capacity = 25 * 1000 * 1000;
@@ -38,5 +39,4 @@ public class GmailTransportConnectionWriter implements SimplexTransportWriter {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
} }
} }
} }

View File

@@ -1,31 +0,0 @@
package net.sf.briar.plugins.file;
import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
class FileListener {
private final String filename;
private final long end;
private final CountDownLatch finished = new CountDownLatch(1);
private volatile File file = null;
FileListener(String filename, long timeout) {
this.filename = filename;
end = System.currentTimeMillis() + timeout;
}
File waitForFile() throws InterruptedException {
finished.await(end - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
return file;
}
void addFile(File f) {
if(filename.equals(f.getName())) {
file = f;
finished.countDown();
}
}
}

View File

@@ -11,14 +11,12 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.simplex.SimplexPlugin; import net.sf.briar.api.plugins.simplex.SimplexPlugin;
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback; import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
import net.sf.briar.api.plugins.simplex.SimplexTransportReader; import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
import net.sf.briar.api.plugins.simplex.SimplexTransportWriter; import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
import net.sf.briar.api.transport.TransportConstants; import net.sf.briar.api.transport.TransportConstants;
import net.sf.briar.util.StringUtils;
import org.apache.commons.io.FileSystemUtils; import org.apache.commons.io.FileSystemUtils;
@@ -32,10 +30,6 @@ public abstract class FilePlugin implements SimplexPlugin {
protected volatile boolean running = false; protected volatile boolean running = false;
private final Object listenerLock = new Object();
private FileListener listener = null; // Locking: listenerLock
protected abstract File chooseOutputDirectory(); protected abstract File chooseOutputDirectory();
protected abstract Collection<File> findFilesByName(String filename); protected abstract Collection<File> findFilesByName(String filename);
protected abstract void writerFinished(File f); protected abstract void writerFinished(File f);
@@ -94,75 +88,6 @@ public abstract class FilePlugin implements SimplexPlugin {
pluginExecutor.execute(new ReaderCreator(f)); pluginExecutor.execute(new ReaderCreator(f));
} }
public SimplexTransportWriter sendInvitation(PseudoRandom r, long timeout) {
if(!running) return null;
return createWriter(createInvitationFilename(r, false));
}
public SimplexTransportReader acceptInvitation(PseudoRandom r,
long timeout) {
if(!running) return null;
String filename = createInvitationFilename(r, false);
return createInvitationReader(filename, timeout);
}
public SimplexTransportWriter sendInvitationResponse(PseudoRandom r,
long timeout) {
if(!running) return null;
return createWriter(createInvitationFilename(r, true));
}
public SimplexTransportReader acceptInvitationResponse(PseudoRandom r,
long timeout) {
if(!running) return null;
String filename = createInvitationFilename(r, true);
return createInvitationReader(filename, timeout);
}
private SimplexTransportReader createInvitationReader(String filename,
long timeout) {
Collection<File> files;
// FIXME: Avoid making alien calls with a lock held
synchronized(listenerLock) {
// Find any matching files that have already arrived
files = findFilesByName(filename);
if(files.isEmpty()) {
// Wait for a matching file to arrive
listener = new FileListener(filename, timeout);
File f;
try {
f = listener.waitForFile();
if(f != null) files.add(f);
} catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting for file");
Thread.currentThread().interrupt();
}
listener = null;
}
}
// Return the first match that can be opened
for(File f : files) {
try {
FileInputStream in = new FileInputStream(f);
return new FileTransportReader(f, in, FilePlugin.this);
} catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
}
}
return null;
}
private String createInvitationFilename(PseudoRandom r, boolean response) {
String digits = StringUtils.toHexString(r.nextBytes(3));
return String.format("%c%s.dat", response ? 'b' : 'a', digits);
}
// Package access for testing
boolean isPossibleInvitationFilename(String filename) {
return filename.toLowerCase().matches("[ab][0-9a-f]{6}.dat");
}
private class ReaderCreator implements Runnable { private class ReaderCreator implements Runnable {
private final File file; private final File file;
@@ -172,13 +97,6 @@ public abstract class FilePlugin implements SimplexPlugin {
} }
public void run() { public void run() {
String filename = file.getName();
if(isPossibleInvitationFilename(filename)) {
// FIXME: Avoid making alien calls with a lock held
synchronized(listenerLock) {
if(listener != null) listener.addFile(file);
}
}
if(isPossibleConnectionFilename(file.getName())) { if(isPossibleConnectionFilename(file.getName())) {
try { try {
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);

View File

@@ -65,10 +65,6 @@ implements RemovableDriveMonitor.Callback {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public boolean supportsInvitations() {
return true;
}
@Override @Override
protected File chooseOutputDirectory() { protected File chooseOutputDirectory() {
try { try {