Author: nextgens
Date: 2007-03-09 15:19:14 +0000 (Fri, 09 Mar 2007)
New Revision: 12055
Added:
trunk/apps/Thaw/src/thaw/gui/MDNSDiscoveryPanel.java
Log:
Thaw: I forgot a file
Added: trunk/apps/Thaw/src/thaw/gui/MDNSDiscoveryPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/gui/MDNSDiscoveryPanel.java
(rev 0)
+++ trunk/apps/Thaw/src/thaw/gui/MDNSDiscoveryPanel.java 2007-03-09
15:19:14 UTC (rev 12055)
@@ -0,0 +1,240 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+
+package thaw.gui;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.jmdns.JmDNS;
+import javax.jmdns.ServiceEvent;
+import javax.jmdns.ServiceInfo;
+import javax.jmdns.ServiceListener;
+import javax.swing.DefaultListModel;
+import javax.swing.GroupLayout;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import thaw.core.Config;
+import thaw.core.Logger;
+import thaw.fcp.FCPConnection;
+
+/**
+ * This panel implements Zeroconf (called Bonjour/RendezVous by apple)
discovery for Thaw
+ *
+ * WARNING: for it to work, you must have a running freenet node on the same
network subnet, using the MDNSDiscovery panel
+ *
+ * @author Florent Daignière <nextgens at freenetproject.org>
+ *
+ * @see http://wiki.freenetproject.org/MDNSDiscoverypanel
+ *
+ * @see http://www.dns-sd.org/ServiceTypes.html
+ * @see http://www.multicastdns.org/
+ * @see http://jmdns.sourceforge.net/
+ *
+ * TODO: implement the "Manual" mode
+ * TODO: maybe we should have a small progressbar shown in a new popup to
introduce a "delay" at startup
+ */
+public class MDNSDiscoveryPanel extends JFrame implements
ListSelectionListener {
+ private static final long serialVersionUID = 1L;
+
+ private static final String FCP_SERVICE_TYPE = "_fcp._tcp.local.";
+
+ private boolean goon = true;
+ private ServiceInfo selectedValue;
+
+ private final JScrollPane panel;
+ private final JProgressBar progressBar;
+ private final JList list;
+ private final DefaultListModel listModel;
+ private final JLabel label;
+
+ private final Config config;
+ private final HashMap foundNodes;
+ private final JmDNS jmdns;
+
+ public MDNSDiscoveryPanel(Config conf) {
+ this.config = conf;
+ this.foundNodes = new HashMap();
+ try {
+ // Spawn the mdns listener
+ this.jmdns = new JmDNS();
+
+ // Start listening for new nodes
+
jmdns.addServiceListener(MDNSDiscoveryPanel.FCP_SERVICE_TYPE, new
FCPMDNSListener(this));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("Error loading
MDNSDiscoveryPanel : " + e.getMessage());
+ }
+
+ // The UI
+ panel = new JScrollPane();
+ progressBar = new JProgressBar(0, 30);
+ list = new JList();
+ listModel = new DefaultListModel();
+ label = new JLabel();
+
+ listModel.addElement("Manual configuration (not recommended) :
NotYetImplemented ;)");
+
+ list.setModel(listModel);
+
list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ list.addListSelectionListener(this);
+
+ panel.setViewportView(list);
+
+ label.setText("Select the freenet node you want to connect to
from the list below :");
+
+ panel.add(progressBar);
+
+ GroupLayout layout = new GroupLayout(this.getContentPane());
+
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(label,
GroupLayout.PREFERRED_SIZE, 430, GroupLayout.PREFERRED_SIZE))
+
.addGroup(layout.createSequentialGroup()
+ .addGap(36, 36,
36)
+
.addComponent(panel, GroupLayout.PREFERRED_SIZE, 380,
GroupLayout.PREFERRED_SIZE))
+ );
+ layout.setVerticalGroup(
+
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(7, 7, 7)
+ .addComponent(label)
+
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(panel,
GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE)
+
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ pack();
+ super.setAlwaysOnTop(true);
+ super.setLocationRelativeTo(this.getParent());
+ this.setTitle("ZeroConf discovery plugin... Please hold on");
+
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ this.setVisible(true);
+
+ Logger.notice(this, "The configuration file doesn't seems to be
valid... MDNSDiscovery is starting!");
+ }
+
+ private class FCPMDNSListener implements ServiceListener {
+ private final MDNSDiscoveryPanel panel;
+
+ public FCPMDNSListener(MDNSDiscoveryPanel panel) {
+ this.panel = panel;
+ }
+
+ public void serviceAdded(ServiceEvent event) {
+ Logger.notice(this, "Service added : " +
event.getName()+"."+event.getType());
+ // Force the gathering of informations
+
jmdns.getServiceInfo(MDNSDiscoveryPanel.FCP_SERVICE_TYPE, event.getName());
+ }
+
+ public synchronized void serviceRemoved(ServiceEvent event) {
+ Logger.notice(this, "Service removed : " +
event.getName()+"."+event.getType());
+ ServiceInfo service = event.getInfo();
+
+ synchronized (panel) {
+ panel.foundNodes.remove(service.getName());
+
panel.listModel.removeElement(service.getName());
+ notify();
+ }
+ }
+
+ public synchronized void serviceResolved(ServiceEvent event) {
+ Logger.debug(this, "Service resolved: " +
event.getInfo());
+ ServiceInfo service = event.getInfo();
+
+ synchronized (panel) {
+ panel.foundNodes.put(service.getName(),
service);
+ panel.listModel.addElement(service.getName());
+ notify();
+ }
+ }
+ }
+
+ /**
+ * The user has selected something: notify the main loop and process
the data.
+ */
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting() == false) {
+ if(list.getSelectedValue() == null) return; // Ignore
the user if he clicks nowhere
+
+ synchronized (this) {
+ selectedValue = (ServiceInfo)
foundNodes.get(list.getSelectedValue());
+ goon = false;
+ notify();
+ }
+ Logger.debug(this, "User has selected :
"+foundNodes.get(list.getSelectedValue()));
+ }
+ }
+
+ /**
+ * The main loop : TheRealMeat(TM)
+ *
+ */
+ public void run() {
+ boolean isConfigValid = false;
+ FCPConnection fcp = null;
+
+ do {
+ // Loop until a selection is done
+ while(goon) {
+ try {
+ synchronized (this) {
+ wait(Long.MAX_VALUE);
+ }
+ } catch (InterruptedException e) {}
+
+ list.repaint();
+ }
+
+ if(selectedValue == null) continue; // TODO: implement
the "manual" popup there
+
+ Logger.debug(this, "We got something from the UI :
let's try to connect");
+
+ // We try to connect to the server
+ fcp = new FCPConnection(selectedValue.getHostAddress(),
selectedValue.getPort(), -1, true, true);
+ isConfigValid = fcp.connect();
+
+ Logger.debug(this, "isConfigValid ="+isConfigValid);
+
+ // Reload, just in case it failed...
+ goon = true;
+ list.removeSelectionInterval(0, foundNodes.size());
+ } while(!isConfigValid);
+
+ Logger.debug(this, "We got something that looks valid from the
UI : let's propagate changes to the config");
+
+ // Save the config. now that we know it's valid
+ config.setValue("nodeAddress", selectedValue.getHostAddress());
+ config.setValue("nodePort", new
Integer(selectedValue.getPort()).toString());
+ try {
+ config.setValue("sameComputer",
(jmdns.getInterface().equals(selectedValue.getAddress()) ? "true" : "false"));
+ } catch (IOException e ) {} // What can we do except assuming
default is fine ?
+
+
+ Logger.info(this, "We are done : configuration has been saved
sucessfully.");
+
+ // Close the fcp socket we have openned, cleanup
+ fcp.disconnect();
+ jmdns.close();
+ this.setVisible(false);
+ }
+
+ /**
+ * Convenient testing function function.
+ */
+ public static void main(String[] args) {
+ new MDNSDiscoveryPanel(new Config("/tmp/conf.ini")).run();
+ System.exit(0);
+ }
+}