diff --git a/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java b/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java index b7c623934..74907f463 100755 --- a/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java +++ b/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java @@ -62,11 +62,11 @@ public class AdHocCommandManager { /** * The session time out in seconds. */ - public static int SESSION_TIMEOUT = 2 * 60; + private static final int SESSION_TIMEOUT = 2 * 60; /** - * Map a XMPPConnection with it AdHocCommandManager. This map have a pair - * key-value for every active connection. + * Map a XMPPConnection with it AdHocCommandManager. This map have a key-value + * pair for every active connection. */ private static Map instances = new ConcurrentHashMap(); @@ -127,19 +127,38 @@ public class AdHocCommandManager { } /** - * Register a new command to this command manager, which is related to a - * connection. The node is an unique identifier of that - * command for the connection related to this command manager. The - * name is the human readable name of the command. - * The class is the class of the command, which must extend - * {@link LocalCommand}. + * Registers a new command with this command manager, which is related to a + * connection. The node is an unique identifier of that command for + * the connection related to this command manager. The name is the + * human readable name of the command. The class is the class of + * the command, which must extend {@link LocalCommand} and have a default + * constructor. * * @param node the unique identifier of the command. * @param name the human readable name of the command. * @param clazz the class of the command, which must extend {@link LocalCommand}. */ - public void registerCommand(String node, final String name, Class clazz) { - AdHocCommandInfo commandInfo = new AdHocCommandInfo(node, name, connection.getUser(), clazz); + public void registerCommand(String node, String name, final Class clazz) { + registerCommand(node, name, new LocalCommandFactory() { + public LocalCommand getInstance() throws InstantiationException, IllegalAccessException { + return (LocalCommand)clazz.newInstance(); + } + }); + } + + /** + * Registers a new command with this command manager, which is related to a + * connection. The node is an unique identifier of that + * command for the connection related to this command manager. The name + * is the human readeale name of the command. The factory generates + * new instances of the command. + * + * @param node the unique identifier of the command. + * @param name the human readable name of the command. + * @param factory a factory to create new instances of the command. + */ + public void registerCommand(String node, final String name, LocalCommandFactory factory) { + AdHocCommandInfo commandInfo = new AdHocCommandInfo(node, name, connection.getUser(), factory); commands.put(node, commandInfo); // Set the NodeInformationProvider that will provide information about @@ -651,11 +670,10 @@ public class AdHocCommandManager { private LocalCommand newInstanceOfCmd(String commandNode, String sessionID) throws XMPPException { - // TODO Evaluate the possibility of using a factory for creating the new instances. AdHocCommandInfo commandInfo = commands.get(commandNode); LocalCommand command; try { - command = (LocalCommand) commandInfo.getCmdClass().newInstance(); + command = (LocalCommand) commandInfo.getCommandInstance(); command.setSessionID(sessionID); command.setName(commandInfo.getName()); command.setNode(commandInfo.getNode()); @@ -684,29 +702,28 @@ public class AdHocCommandManager { } /** - * The ad-hoc command information. - * - * @author Gabriel - * + * Stores ad-hoc command information. */ private static class AdHocCommandInfo { private String node; private String name; private String ownerJID; - private Class cmdClass; + private LocalCommandFactory factory; public AdHocCommandInfo(String node, String name, String ownerJID, - Class cmdClass) + LocalCommandFactory factory) { this.node = node; this.name = name; this.ownerJID = ownerJID; - this.cmdClass = cmdClass; + this.factory = factory; } - public Class getCmdClass() { - return cmdClass; + public LocalCommand getCommandInstance() throws InstantiationException, + IllegalAccessException + { + return factory.getInstance(); } public String getName() { diff --git a/source/org/jivesoftware/smackx/commands/LocalCommandFactory.java b/source/org/jivesoftware/smackx/commands/LocalCommandFactory.java new file mode 100644 index 000000000..11efd2b98 --- /dev/null +++ b/source/org/jivesoftware/smackx/commands/LocalCommandFactory.java @@ -0,0 +1,24 @@ +package org.jivesoftware.smackx.commands; + +/** + * A factory for creating local commands. It's useful in cases where instantiation + * of a command is more complicated than just using the default constructor. For example, + * when arguments must be passed into the constructor or when using a dependency injection + * framework. When a LocalCommandFactory isn't used, you can provide the AdHocCommandManager + * a Class object instead. For more details, see + * {@link AdHocCommandManager#registerCommand(String, String, LocalCommandFactory)}. + * + * @author Matt Tucker + */ +public interface LocalCommandFactory { + + /** + * Returns an instance of a LocalCommand. + * + * @return a LocalCommand instance. + * @throws InstantiationException if creating an instance failed. + * @throws IllegalAccessException if creating an instance is not allowed. + */ + public LocalCommand getInstance() throws InstantiationException, IllegalAccessException; + +} \ No newline at end of file diff --git a/test/org/jivesoftware/smackx/commands/AdHocCommandDiscoTest.java b/test/org/jivesoftware/smackx/commands/AdHocCommandDiscoTest.java index e07ba483d..f184c94f6 100644 --- a/test/org/jivesoftware/smackx/commands/AdHocCommandDiscoTest.java +++ b/test/org/jivesoftware/smackx/commands/AdHocCommandDiscoTest.java @@ -53,10 +53,13 @@ package org.jivesoftware.smackx.commands; import org.jivesoftware.smack.test.SmackTestCase; +import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smackx.packet.DiscoverItems; +import org.jivesoftware.smackx.Form; +import org.jivesoftware.smackx.FormField; /** - * + * AdHocCommand tests. * * @author Matt Tucker */ @@ -70,15 +73,58 @@ public class AdHocCommandDiscoTest extends SmackTestCase { super(arg0); } - public void testInvitation() { + public void testAdHocCommands() { try { AdHocCommandManager manager1 = AdHocCommandManager.getAddHocCommandsManager(getConnection(0)); manager1.registerCommand("test", "test node", LocalCommand.class); + + manager1.registerCommand("test2", "test node", new LocalCommandFactory() { + public LocalCommand getInstance() throws InstantiationException, IllegalAccessException { + return new LocalCommand() { + public boolean isLastStage() { + return true; + } + + public boolean hasPermission(String jid) { + return true; + } + + public void execute() throws XMPPException { + Form result = new Form(Form.TYPE_RESULT); + FormField resultField = new FormField("test2"); + resultField.setLabel("test node"); + resultField.addValue("it worked"); + result.addField(resultField); + setForm(result); + } + + public void next(Form response) throws XMPPException { + // + } + + public void complete(Form response) throws XMPPException { + // + } + + public void prev() throws XMPPException { + // + } + + public void cancel() throws XMPPException { + // + } + }; + } + }); AdHocCommandManager manager2 = AdHocCommandManager.getAddHocCommandsManager(getConnection(1)); DiscoverItems items = manager2.discoverCommands(getFullJID(0)); assertTrue("Disco for command test failed", items.getItems().next().getNode().equals("test")); + + RemoteCommand command = manager2.getRemoteCommand(getFullJID(0), "test2"); + command.execute(); + assertEquals("Disco for command test failed", command.getForm().getField("test2").getValues().next(), "it worked"); } catch (Exception e) { fail(e.getMessage());