Spark

What Are Sparkplugs?

Sparkplugs dynamically extend the features of the Spark instant messaging client. Use Sparkplugs to customize Spark for your business or organization or to add an innovative twist to instant messaging. The extensive plugin API allows for complete client flexibility but is still simple and (we hope!) fun to use.

This guide provides a high level overview of the Sparkplug API and examples of several common client customizations. Or, jump directly into the Javadocs.

Once I Build It, Then What?

After you've built your amazingly cool Sparkplug, it's easy to rollout to your users. Just have them drop it in the plugins directory of their Spark installation. If your Sparkplug is generally useful, we hope you'll share it with the whole Spark community! To make your Sparkplug available via the public repository at jivesoftware.org, submit it to plugins@jivesoftware.org.

Contents

This document contains the following information:

Overview of the Spark Client

The Spark client is designed with the idea that most users find the different aspects of a chat client familiar and easy to use. All components you see below are either accessible from the Workspace or ChatRoom object and can be manipulated based on your needs.


Overview of the Spark API

The Spark API provides a framework for adding extensions on top of the protocol and/or UI of the Spark client. For example, you could write your own message filter or add a button to a chat room and send files using the File Transfer API. The Spark API has the following characteristics:

Structure of a Plugin

Plugins are shipped as compressed JAR (Java Archive) files. The files in a plugin archive are as follows:

Plugin Structure
myplugin.jar!/
 |- plugin.xml     <- Plugin definition file
 |- libs/          <- Contains all the class archives needed to run this plugin.

The plugin.xml file specifies the main Plugin class. A sample file might look like the following:

Sample plugin.xml
<?xml version="1.0" encoding="UTF-8"?>

  <!-- Google Plugin Structure -->
      <plugin>
        <name>Google Desktop Plugin</name>
        <class>com.examples.plugins.GooglePlugin</class>
        <author>Derek DeMoro</author>
        <version>1.0</version>
        <description>Enables users to find files and emails relating to users using Google Desktop technology.</description>
        <email>ddman@jivesoftware.com</email>
      </plugin>

Installing your Plugin

You only need to drop your newly created jar file into the plugins directory of your Spark client install.

Directory Structure
Spark/
 |- plugins/     <- Put your Sparkplug jar file here
 |- lib/       <- The main classes and libraries needed to run your plugin.
 |- resources/ <- Contains other supportive documents and libraries.
 |- docs/ <- Help Manuals and the JavaDoc to help you develop your own plugins.

Your plugin class must implement the Plugin interface from the Spark Client API. The Plugin interface has methods for initializing and shutting down the plugin.

Getting Started Writing Sparkplugs

In order to build your own Sparkplugs, you will need to setup your project properly to have all items in your classpath. With the Sparkplug.zip or Sparplug.tar.gz you have just extracted, you should see the following contents:

Directory Structure
Sparkplugs/
 |- build/     <- Simple structure to allow you to easily build your plugins using ANT.
 |- images/       <-  Images used in this guide.
 |- plugin_development_guide.html/ <- The complete development guide (this document).
 |- api/  <- Contains the Sparkplug Javadocs.
 |- spark/ <- The spark build structure you will need for classpath purposes
    |-bin    <- Contacts the startup.bat which starts up Spark for testing.
    |-lib    <- Contains all the archives needed to run Spark.
    |-logs   <- Where all logs are stored.
    |-plugins <- Location where all plugins should be deployed to.
    |-resources <- Contains native libraries for running OS specific operations.

To setup a project to run Spark within your IDE, you will need to the following:

We have also provided a build structure to easily build and deploy your own plugins directly into your Spark test bed. To use, read the file in the builder/ directory.

Spark How-To's

All code samples can be found in the examples.jar file located here.

How do I create a simple plugin?

  1. Implement Plugin.
Simple Plugin
package org.jivesoftware.spark.examples;

import org.jivesoftware.spark.plugin.Plugin;

/**
 * Implements the Spark Plugin framework to display the different possibilities using
 * Spark.
 */
public class ExamplePlugin implements Plugin {

    /**
     * Called after Spark is loaded to initialize the new plugin.
     */
    public void initialize() {
        System.out.println("Welcome To Spark");

    }

    /**
     * Called when Spark is shutting down to allow for persistence of information
     * or releasing of resources.
     */
    public void shutdown() {

    }

    /**
     * Return true if the Spark can shutdown on users request.
     * @return true if Spark can shutdown on users request.
     */
    public boolean canShutDown() {
        return true;
    }

    /**
    * Is called when a user explicitly asked to uninstall this plugin.
    * The plugin owner is responsible to clean up any resources and
    * remove any components install in Spark.
    */
    public void uninstall(){
       // Remove all resources belonging to this plugin.
    }
}

How to add your own Tab to the Spark Workspace?

  1. Implement Plugin.
  2. Retrieve the Workspace which is the UI for Spark.
  3. Retrieve the WorkspacePane which is the Tabbed Pane used by Spark.
  4. Add your own tab.
Add a Tab to Spark
public class ExamplePlugin implements Plugin {
.
.
.
    /**
     * Adds a tab to Spark
     */
    private void addTabToSpark(){
         // Get Workspace UI from SparkManager
        Workspace workspace = SparkManager.getWorkspace();

        // Retrieve the Tabbed Pane from the WorkspaceUI.
        JTabbedPane tabbedPane = workspace.getWorkspacePane();

        // Add own Tab.
        tabbedPane.addTab("My Plugin", new JButton("Hello"));
    }
.
.
.
}

How do I add a context menu listener to the contact list?

  1. Implement Plugin.
  2. Retrieve the ContactList which is part of Spark's Workspace.
  3. Add ContactListListener.
Add a ContextMenu Listener to ContactList
  private void addContactListListener(){
         // Get Workspace UI from SparkManager
        Workspace workspace = SparkManager.getWorkspace();

        // Retrieve the ContactList from the Workspace
        ContactList contactList = workspace.getContactList();

        // Create an action to add to the Context Menu
        final Action sayHelloAction = new AbstractAction() {
            public void actionPerformed(ActionEvent actionEvent) {
                JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Welcome to Spark");
            }
        };

        sayHelloAction.putValue(Action.NAME, "Say Hello To Me");


        // Add own Tab.
        contactList.addContextMenuListener(new ContextMenuListener() {
            public void poppingUp(Object object, JPopupMenu popup) {
                if(object instanceof ContactItem){
                    popup.add(sayHelloAction);
                }
            }

            public void poppingDown(JPopupMenu popup) {

            }

            public boolean handleDefaultAction(MouseEvent e) {
                return false;
            }
        });
    }

How do I add my own ContextMenu Listener to a ChatRoom

  1. Implement Plugin.
  2. Add a ChatRoomListener to the ChatManager.
  3. Get either the TranscriptWindow or ChatInputEditor from the ChatRoom.
  4. Add a ContactMenuListener to the ChatArea.
Add a ContextMenuListener to a ChatRoom, TranscriptWindow or ChatInputEditor
    private void addContactListenerToChatRoom() {
       // Retrieve a ChatManager from SparkManager
        ChatManager chatManager = SparkManager.getChatManager();

        final ContextMenuListener listener = new ContextMenuListener() {
            public void poppingUp(Object object, JPopupMenu popup) {
                final TranscriptWindow chatWindow = (TranscriptWindow)object;
                Action clearAction = new AbstractAction() {
                    public void actionPerformed(ActionEvent actionEvent) {
                        try {
                            chatWindow.insert("My own text :)");
                        }
                        catch (BadLocationException e) {
                            e.printStackTrace();
                        }
                    }
                };

                clearAction.putValue(Action.NAME, "Insert my own text");
                popup.add(clearAction);
            }

            public void poppingDown(JPopupMenu popup) {

            }

            public boolean handleDefaultAction(MouseEvent e) {
                return false;
            }
        };

        // Add a ChatRoomListener to the ChatManager to allow for notifications
        // when a room is being opened. Note: I will use a ChatRoomListenerAdapter for brevity.
        chatManager.addChatRoomListener(new ChatRoomListenerAdapter() {
            public void chatRoomOpened(ChatRoom room) {
                room.getTranscriptWindow().addContextMenuListener(listener);
            }

            public void chatRoomLeft(ChatRoom room) {
                room.getTranscriptWindow().removeContextMenuListener(listener);
            }
        });
    }

How do I add my own Menu to Spark?

  1. Implement Plugin.
  2. Retrieve the MainWindow from SparkManager.
  3. Either create a new Menu or add a MenuItem to one of the pre-existing menus.
Add a Menu To Spark
    /**
     * Adds a new menu and child menu item to Spark.
     */
    private void addMenuToSpark(){
        // Retrieve the MainWindow UI from Spark.
        final MainWindow mainWindow = SparkManager.getMainWindow();

        // Create new Menu
        JMenu myPluginMenu = new JMenu("My Plugin Menu");

        // Create Action to test Menu install.
        Action showMessage = new AbstractAction() {
            public void actionPerformed(ActionEvent actionEvent) {
                JOptionPane.showMessageDialog(mainWindow, "Yeah, It works.");
            }
        };

        // Give the menu item a name.
        showMessage.putValue(Action.NAME, "Check if it works");

        // Add to Menu
        myPluginMenu.add(showMessage);

        // Add Menu To Spark
        mainWindow.getJMenuBar().add(myPluginMenu);
    }

How do I add a button to a Chat Room?

  1. Implement Plugin.
  2. Add a ChatRoomListener to ChatManager.
  3. When the room is opened, add your ChatRoomButton to the ToolBar of the ChatRoom.
Add a button to a Chat Room
    /**
     * Adds a button to each Chat Room that is opened.
     */
    private void addChatRoomButton(){
        // Retrieve ChatManager from the SparkManager
        ChatManager chatManager = SparkManager.getChatManager();

        // Create a new ChatRoomButton.
        final ChatRoomButton button = new ChatRoomButton("Push Me");


        // Add to a new ChatRoom when the ChatRoom opens.
        chatManager.addChatRoomListener(new ChatRoomListenerAdapter() {
            public void chatRoomOpened(ChatRoom room) {
                room.getToolBar().addChatRoomButton(button);
            }

            public void chatRoomLeft(ChatRoom room) {
                room.getToolBar().removeChatRoomButton(button);
            }
        });
    }

How do I add my own searching feature in Spark like the User Search or Google Search in Firefox?

  1. Implement Plugin.
  2. Create a searchable object by implementing the Searchable interface.
  3. Add the Searchable implementation to the SearchManager.
Add a search feature to Spark like User Search or Google Search in Firefox
    /**
     * Called after Spark is loaded to initialize the new plugin.
     */
    public void initialize() {
        // Register new Searchable object "SearchMe" with the SearchManager.
        SearchManager searchManager = SparkManager.getSearchManager();
        searchManager.addSearchService(new SearchMe());
    } 
See the SearchMe code below.
 
    
package org.jivesoftware.spark.examples;

import org.jivesoftware.spark.search.Searchable;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.resource.LaRes;

import javax.swing.Icon;
import javax.swing.JOptionPane;

/**
 * A simple example of how to integrate ones own search into Spark.
 */
public class SearchMe implements Searchable {

    /**
     * The icon to show in the search box.
     * @return the icon.
     */
    public Icon getIcon() {
        return LaRes.getImageIcon(LaRes.SMALL_AGENT_IMAGE);
    }

    /**
     * Returns the name of this search object that is displayed in the drop down box.
     * @return the name.
     */
    public String getName() {
        return "Searches Nothing Really";
    }

    /**
     * Returns the text that should be displayed in grey when this searchable object
     * is initially selected.
     * @return the text.
     */
    public String getDefaultText() {
        return "Click to search me.";
    }

    /**
     * Returns the text to display in the tooltip.
     * @return the tooltip text.
     */
    public String getToolTip() {
        return "Shows an example of integrating ones own search into Spark.";
    }

    /**
     * Is called when a user hits "Enter" key.
     * @param query the query the user is searching for.
     */
    public void search(String query) {
        JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Nothing Found :(");
    }
}

How can I intercept a File Transfer request?

  1. Implement Plugin.
  2. Implement TransferListener.
  3. Register your TransferListener.
Intercept File Transfer Requests
    /**
     * Listen for incoming transfer requests and either handle them yourself, or pass them
     * off to be handled by the next listener. If no one handles it, then Spark will handle it.
     */
    private void addTransferListener(){

        SparkTransferManager transferManager = SparkManager.getTransferManager();

        transferManager.addTransferListener(new TransferListener() {
            public boolean handleTransfer(FileTransferRequest request) {
                // If I wanted to handle it, take the request, accept it and get the inputstream.
                
                // Otherwise, return false.
                return false;
            }
        });
    }

How can I send a file to another user?

  1. Implement Plugin.
  2. Get the full jid of the user via the UserManager.
  3. Get the SparkTransferManager and send the file.
Send a file to another user
    /**
     * Sends a file to a user in your ContactList.
     */
    private void sendFile(){
        // Retrieve SparkTransferManager from the SparkManager.
        SparkTransferManager transferManager = SparkManager.getTransferManager();

        // In order to send a file to a person, you will need to know their full Jabber
        // ID.

        // Retrieve the Jabber ID for a user via the UserManager. This can
        // return null if the user is not in the ContactList or is offline.
        UserManager userManager = SparkManager.getUserManager();
        String jid = userManager.getJIDFromNickname("Matt");
        if(jid != null){
            transferManager.sendFile(new File("MyFile.txt"), jid);
        }
    }

How can I control the UI and event handling of a ContactItem?

  1. Implement Plugin.
  2. Get the ContactList.
  3. Get a ContactItem(s) based on a user's jid.
  4. Add your own ContactItemHandler to the ContactItem.
Control the UI and event handling of a ContactItem
    /**
     * Controls the UI of a ContactItem.
     */
    private void handleUIAndEventsOfContactItem(){

        ContactList contactList = SparkManager.getWorkspace().getContactList();

        ContactItem item = contactList.getContactItemByJID("paul@jivesoftware.com/spark");

        ContactItemHandler handler = new ContactItemHandler() {
            /**
             * Called when this users presence changes. You are responsible for changing the
             * icon (or not) of this contact item.
             * @param presence the users new presence.
             */
            public void handlePresence(Presence presence) {

            }

            /**
             * Is called when a user double-clicks the item.
             * @return true if you are handling the event.
             */
            public boolean handleDoubleClick() {
                return false;
            }
        };

        item.setHandler(handler);
    }

How can I be notified when the Spark user changes their presence?

  1. Implement Plugin.
  2. Get the SessionManager from SparkManager.
  3. Add your own PresenceListener to SessionManager.
Receive notification when the Spark user changes their presence
    /**
     * Allows a plugin to be notified when the Spark users changes their
     * presence.
     */
    private void addPersonalPresenceListener(){
        SessionManager sessionManager = SparkManager.getSessionManager();

        sessionManager.addPresenceListener(new PresenceListener() {

            /**
             * Spark user changed their presence.
             * @param presence the new presence.
             */
            public void presenceChanged(Presence presence) {
                
            }
        });
    }

How can I add a message filter?

  1. Implement Plugin.
  2. Get the ChatManager from SparkManager.
  3. Create an instance of Message Filter.
  4. Register with the ChatManager.
Adding own Message Filter
    /**
     * Installs a new MessageFilter.
     */
    private void installMessageFilter() {
        // Retrieve the ChatManager from SparkManager
        ChatManager chatManager = SparkManager.getChatManager();

        MessageFilter messageFilter = new MessageFilter() {
            public void filter(Message message) {
                String currentBody = message.getBody();
                currentBody = currentBody.replaceAll("bad words", "good words");
                message.setBody(currentBody);
            }
        };

        chatManager.addMessageFilter(messageFilter);

        // Just remember to remove your filter if need be.
    }

How can I create a person-to-person Chat Room

  1. Implement Plugin.
  2. Get the ChatManager from SparkManager.
  3. Create a new ChatRoom using the ChatManager.
  4. Optionally make it the active ChatRoom using the ChatContainer.
Creating Person-to-Person Chat Room
    /**
     * Creates a person to person Chat Room and makes it the active chat.
     */
    private void createPersonToPersonChatRoom(){
        
        // Get the ChatManager from Sparkmanager
        ChatManager chatManager = SparkManager.getChatManager();
        
        // Create the room.
        ChatRoom chatRoom = chatManager.createChatRoom("don@jivesoftware.com", "Don The Man", "The Chat Title");
        
        // If you wish to make this the active chat room.
        
        // Get the ChatContainer (This is the container for all Chat Rooms)
        ChatContainer chatContainer = chatManager.getChatContainer();
        
        // Ask the ChatContainer to make this chat the active chat.
        chatContainer.activateChatRoom(chatRoom);
    }

How can I create a public Conference room?

  1. Implement Plugin.
  2. Get the ChatManager from SparkManager.
  3. Create a new conference ChatRoom using the ChatManager.
  4. Optionally make it the active ChatRoom using the ChatContainer.
Creating a Conference Room
    /**
     * Creates a person to person Chat Room and makes it the active chat.
     */
    private void createConferenceRoom() {

        // Get the ChatManager from Sparkmanager
        ChatManager chatManager = SparkManager.getChatManager();

        Collection serviceNames = null;

        // Get the service name you wish to use.
        try {
            serviceNames = MultiUserChat.getServiceNames(SparkManager.getConnection());
        }
        catch (XMPPException e) {
            e.printStackTrace();
        }

        // Create the room.
        ChatRoom chatRoom = chatManager.createConferenceRoom("BusinessChat", (String)serviceNames.toArray()[0]);

        // If you wish to make this the active chat room.

        // Get the ChatContainer (This is the container for all Chat Rooms)
        ChatContainer chatContainer = chatManager.getChatContainer();

        // Ask the ChatContainer to make this chat the active chat.
        chatContainer.activateChatRoom(chatRoom);
    }
}

How can I add my own Preferences?

  1. Implement Plugin.
  2. Create a class that implements Preference.
  3. Create a UI to associate with the Preference.
  4. Register your new Preference with the PreferenceManager.
Creating a Preference

How to show an alert, like when a new message comes in?

How to show an alert, like when a new message comes in?
    // Get the ChatContainer from the ChatManager.
    
     ChatContainer chatContainer = ChatManager.getChatContainer();
     
     // Get the room you wish to be notified.
     ChatRoom chatRoom = chatContainer.getActiveChatRoom();
     chatContainer.startFlashing(chatRoom);