AdHocCommandHandler.java 9.7 KB
Newer Older
1 2 3 4
/**
 * $Revision: 3023 $
 * $Date: 2005-11-02 18:00:15 -0300 (Wed, 02 Nov 2005) $
 *
5
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
6
 *
7 8 9 10 11 12 13 14 15 16 17
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
18 19
 */

20
package org.jivesoftware.openfire.commands;
21 22 23

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
24 25 26 27 28 29
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.commands.admin.*;
import org.jivesoftware.openfire.commands.admin.group.*;
import org.jivesoftware.openfire.commands.admin.user.AddUser;
30
import org.jivesoftware.openfire.commands.admin.user.DeleteUser;
31 32 33
import org.jivesoftware.openfire.commands.admin.user.AuthenticateUser;
import org.jivesoftware.openfire.commands.admin.user.ChangeUserPassword;
import org.jivesoftware.openfire.commands.admin.user.UserProperties;
34
import org.jivesoftware.openfire.commands.clearspace.ChangeSharedSecret;
35
import org.jivesoftware.openfire.commands.clearspace.GenerateNonce;
36 37
import org.jivesoftware.openfire.commands.clearspace.SystemAdminAdded;
import org.jivesoftware.openfire.commands.clearspace.SystemAdminRemoved;
38
import org.jivesoftware.openfire.commands.event.*;
39 40
import org.jivesoftware.openfire.disco.*;
import org.jivesoftware.openfire.handler.IQHandler;
41
import org.xmpp.forms.DataForm;
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;

import java.util.*;

/**
 * An AdHocCommandHandler is responsbile for providing discoverable information about the
 * supported commands and for handling commands requests. This is an implementation of JEP-50:
 * Ad-Hoc Commands.<p>
 *
 * Ad-hoc commands that require user interaction will have one or more stages. For each stage the
 * user will complete a data form and send it back to the server. The data entered by the user is
 * kept in a SessionData. Instances of {@link AdHocCommand} are stateless. In order to prevent
 * "bad" users from consuming all system memory there exists a limit of simultaneous commands that
 * a user might perform. Configure the system property <tt>"xmpp.command.limit"</tt> to control
 * this limit. User sessions will also timeout and their data destroyed if they have not been
 * executed within a time limit since the session was created. The default timeout value is 10
 * minutes. The timeout value can be modified by setting the system property
 * <tt>"xmpp.command.timeout"</tt>.<p>
 *
 * New commands can be added dynamically by sending the message {@link #addCommand(AdHocCommand)}.
 * The command will immediatelly appear in the disco#items list and might be executed by those
 * users with enough execution permissions.
 *
 * @author Gaston Dombiak
 */
public class AdHocCommandHandler extends IQHandler
        implements ServerFeaturesProvider, DiscoInfoProvider, DiscoItemsProvider {

    private static final String NAMESPACE = "http://jabber.org/protocol/commands";

    private String serverName;
    private IQHandlerInfo info;
    private IQDiscoInfoHandler infoHandler;
    private IQDiscoItemsHandler itemsHandler;
    /**
78
     * Manager that keeps the list of ad-hoc commands and processing command requests.
79
     */
80
    private AdHocCommandManager manager;
81 82 83 84

    public AdHocCommandHandler() {
        super("Ad-Hoc Commands Handler");
        info = new IQHandlerInfo("command", NAMESPACE);
85
        manager = new AdHocCommandManager();
86 87
    }

88 89
    @Override
	public IQ handleIQ(IQ packet) throws UnauthorizedException {
90
        return manager.process(packet);
91 92
    }

93 94
    @Override
	public IQHandlerInfo getInfo() {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
        return info;
    }

    public Iterator<String> getFeatures() {
        ArrayList<String> features = new ArrayList<String>();
        features.add(NAMESPACE);
        return features.iterator();
    }

    public Iterator<Element> getIdentities(String name, String node, JID senderJID) {
        ArrayList<Element> identities = new ArrayList<Element>();
        Element identity = DocumentHelper.createElement("identity");
        identity.addAttribute("category", "automation");
        identity.addAttribute("type", NAMESPACE.equals(node) ? "command-list" : "command-node");
        identities.add(identity);
        return identities.iterator();
    }

    public Iterator<String> getFeatures(String name, String node, JID senderJID) {
        return Arrays.asList(NAMESPACE, "jabber:x:data").iterator();
    }

117
    public DataForm getExtendedInfo(String name, String node, JID senderJID) {
118 119 120 121 122 123 124 125 126
        return null;
    }

    public boolean hasInfo(String name, String node, JID senderJID) {
        if (NAMESPACE.equals(node)) {
            return true;
        }
        else {
            // Only include commands that the sender can execute
127
            AdHocCommand command = manager.getCommand(node);
128 129 130 131
            return command != null && command.hasPermission(senderJID);
        }
    }

132 133
    public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
        List<DiscoItem> answer = new ArrayList<DiscoItem>();
134 135 136 137
        if (!NAMESPACE.equals(node)) {
            answer = Collections.emptyList();
        }
        else {
138
            for (AdHocCommand command : manager.getCommands()) {
139 140
                // Only include commands that the sender can invoke (i.e. has enough permissions)
                if (command.hasPermission(senderJID)) {
141 142 143 144
					final DiscoItem item = new DiscoItem(new JID(serverName),
							command.getLabel(), command.getCode(), null);
					answer.add(item);
				}
145 146 147 148 149
            }
        }
        return answer.iterator();
    }

150 151
    @Override
	public void initialize(XMPPServer server) {
152
        super.initialize(server);
153
        serverName = server.getServerInfo().getXMPPDomain();
154 155 156 157
        infoHandler = server.getIQDiscoInfoHandler();
        itemsHandler = server.getIQDiscoItemsHandler();
    }

158 159
    @Override
	public void start() throws IllegalStateException {
160 161 162 163 164 165 166
        super.start();
        infoHandler.setServerNodeInfoProvider(NAMESPACE, this);
        itemsHandler.setServerNodeInfoProvider(NAMESPACE, this);
        // Add the "out of the box" commands
        addDefaultCommands();
    }

167 168
    @Override
	public void stop() {
169 170 171 172
        super.stop();
        infoHandler.removeServerNodeInfoProvider(NAMESPACE);
        itemsHandler.removeServerNodeInfoProvider(NAMESPACE);
        // Stop commands
173
        for (AdHocCommand command : manager.getCommands()) {
174 175 176 177 178 179 180 181 182 183 184 185
            stopCommand(command);
        }
    }

    /**
     * Adds a new command to the list of supported ad-hoc commands by this server. The new
     * command will appear in the discoverable items list and will be executed for those users
     * with enough permission.
     *
     * @param command the new ad-hoc command to add.
     */
    public void addCommand(AdHocCommand command) {
186
        manager.addCommand(command);
187 188 189 190 191 192 193 194 195 196
        startCommand(command);
    }

    /**
     * Removes the command from the list of ad-hoc commands supported by this server. The command
     * will no longer appear in the discoverable items list.
     *
     * @param command the ad-hoc command to remove.
     */
    public void removeCommand(AdHocCommand command) {
197
        if (manager.removeCommand(command)) {
198 199 200 201 202 203
            stopCommand(command);
        }
    }

    private void addDefaultCommands() {
        // TODO Complete when out of the box commands are implemented
204 205 206 207 208
        addCommand(new GetNumberActiveUsers());
        addCommand(new GetNumberOnlineUsers());
        addCommand(new GetNumberUserSessions());
        addCommand(new GetListActiveUsers());
        addCommand(new GetUsersPresence());
209 210 211 212 213 214 215
        addCommand(new GetListGroups());
        addCommand(new GetListGroupUsers());
        addCommand(new AddGroupUsers());
        addCommand(new DeleteGroupUsers());
        addCommand(new AddGroup());
        addCommand(new UpdateGroup());
        addCommand(new DeleteGroup());
216
        addCommand(new AddUser());
217
        addCommand(new DeleteUser());
218
        addCommand(new AuthenticateUser());
219
        addCommand(new ChangeUserPassword());
220
        addCommand(new UserProperties());
221
        addCommand(new PacketsNotification());
222
        addCommand(new GetServerStats());
223
        addCommand(new HttpBindStatus());
224
        addCommand(new ChangeSharedSecret());
225 226 227 228 229 230 231 232 233 234 235 236 237
        addCommand(new UserCreated());
        addCommand(new UserModified());
        addCommand(new UserDeleting());
        addCommand(new GroupCreated());
        addCommand(new GroupDeleting());
        addCommand(new GroupModified());
        addCommand(new GroupMemberAdded());
        addCommand(new GroupMemberRemoved());
        addCommand(new GroupAdminAdded());
        addCommand(new GroupAdminRemoved());
        addCommand(new VCardCreated());
        addCommand(new VCardDeleting());
        addCommand(new VCardModified());
238 239
        addCommand(new GetAdminConsoleInfo());
        addCommand(new GenerateNonce());
240 241
        addCommand(new SystemAdminAdded());
        addCommand(new SystemAdminRemoved());
242 243 244 245 246 247 248 249 250 251 252 253
    }

    private void startCommand(AdHocCommand command) {
        infoHandler.setServerNodeInfoProvider(command.getCode(), this);
        itemsHandler.setServerNodeInfoProvider(command.getCode(), this);
    }

    private void stopCommand(AdHocCommand command) {
        infoHandler.removeServerNodeInfoProvider(command.getCode());
        itemsHandler.removeServerNodeInfoProvider(command.getCode());
    }
}