/* D-Bus Java Viewer Copyright (c) 2006 Peter Cox This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 2 or the Academic Free Licence Version 2.1. Full licence texts are included in the COPYING file with this program. */ package org.freedesktop.dbus.viewer; import static org.freedesktop.dbus.Gettext._; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.TableModel; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.freedesktop.DBus; import org.freedesktop.DBus.Introspectable; import org.freedesktop.dbus.DBusConnection; import org.freedesktop.dbus.UInt32; import org.freedesktop.dbus.exceptions.DBusException; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * A viewer for DBus * * goal is to replicate the functionality of kdbus with Java smarts * * @author pete * @since 29/01/2006 */ public class DBusViewer { private static final Map<String, Integer> CONNECTION_TYPES = new HashMap<String, Integer>(); static { CONNECTION_TYPES.put("System", DBusConnection.SYSTEM); CONNECTION_TYPES.put("Session", DBusConnection.SESSION); } /** Create the DBusViewer * * @param connectionTypes The map of connection types */ public DBusViewer(final Map<String, Integer> connectionTypes) { connections = new ArrayList<DBusConnection>(connectionTypes.size()); SwingUtilities.invokeLater(new Runnable() { @SuppressWarnings("synthetic-access") public void run() { final JTabbedPane tabbedPane = new JTabbedPane(); addTabs(tabbedPane, connectionTypes); final JFrame frame = new JFrame("Dbus Viewer"); frame.setContentPane(tabbedPane); frame.setSize(600, 400); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { frame.dispose(); for (DBusConnection connection : connections) { connection.disconnect(); } System.exit(0); } }); frame.setVisible(true); } }); } private List<DBusConnection> connections; /** * @param args */ public static void main(String[] args) { new DBusViewer(CONNECTION_TYPES); } /** Add tabs for each supplied connection type * @param tabbedPane The tabbed pane * @param connectionTypes The connection */ private void addTabs(final JTabbedPane tabbedPane, final Map<String, Integer> connectionTypes) { for (final String key : connectionTypes.keySet()) { final JLabel label = new JLabel(_("Processing DBus for ") + key); tabbedPane.addTab(key, label); } Runnable loader = new Runnable() { @SuppressWarnings("synthetic-access") public void run() { boolean users = true, owners = true; for (final String key : connectionTypes.keySet()) { try { DBusConnection conn = DBusConnection .getConnection(connectionTypes.get(key)); connections.add(conn); final TableModel tableModel = listDBusConnection(users, owners, conn); SwingUtilities.invokeLater(new Runnable() { public void run() { int index = tabbedPane.indexOfTab(key); final JTable table = new JTable(tableModel); JScrollPane scrollPane = new JScrollPane(table); JPanel tab = new JPanel(new BorderLayout()); tab.add(scrollPane, BorderLayout.CENTER); JPanel southPanel = new JPanel(); final JButton button = new JButton(new IntrospectAction(table)); southPanel.add(button); tab.add(southPanel, BorderLayout.SOUTH); tabbedPane.setComponentAt(index, tab); } }); } catch (final DBusException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { public void run() { int index = tabbedPane.indexOfTab(key); JLabel label = (JLabel) tabbedPane .getComponentAt(index); label .setText(_("Could not load Dbus information for ") + key + ":" + e.getMessage()); } }); } catch (final DBusExecutionException e) { e.printStackTrace(); SwingUtilities.invokeLater(new Runnable() { public void run() { int index = tabbedPane.indexOfTab(key); JLabel label = (JLabel) tabbedPane .getComponentAt(index); label .setText(_("Could not load Dbus information for ") + key + ":" + e.getMessage()); } }); } } } }; final Thread thread = new Thread(loader); thread.setName("DBus Loader"); thread.start(); } /* based on code from org.freedesktop.dbus.ListDBus */ private DBusTableModel listDBusConnection(boolean users, boolean owners, DBusConnection conn) throws DBusException { DBusTableModel model = new DBusTableModel(); DBus dbus = conn.getRemoteObject("org.freedesktop.DBus", "/org/freedesktop/DBus", DBus.class); String[] names = dbus.ListNames(); ParsingContext p = new ParsingContext(conn); for (String name : names) { List<DBusEntry> results = new ArrayList<DBusEntry>(); try { //String objectpath = '/' + name.replace('.', '/'); p.visitNode(name,"/"); } catch (DBusException e) { e.printStackTrace(); } catch (DBusExecutionException e) { e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } results = p.getResult(); p.reset(); if (results.size()>0) { if (users) try { final UInt32 user = dbus.GetConnectionUnixUser(name); for (DBusEntry entry : results) { entry.setUser(user); } } catch (DBusExecutionException DBEe) { } if (!name.startsWith(":") && owners) { try { final String owner = dbus.GetNameOwner(name); for (DBusEntry entry : results) { entry.setOwner(owner); } } catch (DBusExecutionException DBEe) { } } for (DBusEntry entry : results) { model.add(entry); } } } return model; } private final static String DOC_TYPE = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">"; class ParsingContext { private DBusConnection conn; private DocumentBuilder builder; private List<DBusEntry> result; ParsingContext(DBusConnection conn) { this.conn = conn; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e1) { // TODO Auto-generated catch block throw new RuntimeException(_("Error during parser init: ")+e1.getMessage(),e1); } reset(); } DBusEntry addEntry(String name, String path) throws DBusException { DBusEntry entry = new DBusEntry(); entry.setName(name); entry.setPath(path); Introspectable introspectable = conn.getRemoteObject(name, path, Introspectable.class); entry.setIntrospectable(introspectable); result.add(entry); return entry; } public void visitNode(String name, String path) throws DBusException, SAXException, IOException { System.out.println("visit "+name+":"+path); if ("/org/freedesktop/DBus/Local".equals(path)) { // this will disconnects us. return; } DBusEntry e = addEntry(name, path); String introspectData = e.getIntrospectable().Introspect(); Document document = builder.parse(new InputSource(new StringReader(introspectData.replace(DOC_TYPE, "")))); Element root = document.getDocumentElement(); NodeList children = root.getChildNodes(); for (int i=0;i<children.getLength();i++) { Node node = children.item(i); if (Node.ELEMENT_NODE != node.getNodeType()) { continue; } if ("node".equals(node.getNodeName())) { Node nameNode = node.getAttributes().getNamedItem("name"); if (nameNode!=null) { try { if (path.endsWith("/")) { visitNode(name, path + nameNode.getNodeValue()); } else { visitNode(name, path + '/' + nameNode.getNodeValue()); } } catch (DBusException ex) { ex.printStackTrace(); } } } } } public List<DBusEntry> getResult() { return result; } void reset() { result = new ArrayList<DBusEntry>(); } } }