⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adhoccommandmanager.java

📁 openfire 服务器源码下载
💻 JAVA
字号:
/** * $Revision: $ * $Date: $ * * Copyright (C) 2008 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution, or a commercial license * agreement with Jive. */package org.jivesoftware.openfire.commands;import org.dom4j.Element;import org.dom4j.QName;import org.jivesoftware.util.JiveGlobals;import org.jivesoftware.util.StringUtils;import org.xmpp.forms.DataForm;import org.xmpp.forms.FormField;import org.xmpp.packet.IQ;import org.xmpp.packet.PacketError;import java.util.Collection;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.atomic.AtomicInteger;/** * An AdHocCommandManager is responsible for keeping the list of available commands offered * by a service and for processing commands requests. Typically, instances of this class * are private to the service offering ad-hoc commands. * * @author Gaston Dombiak */public class AdHocCommandManager {    private static final String NAMESPACE = "http://jabber.org/protocol/commands";    /**     * Map that holds the offered commands by this service. Note: Key=commandCode, Value=command.     * commandCode matches the node attribute sent by command requesters.     */    private Map<String, AdHocCommand> commands = new ConcurrentHashMap<String, AdHocCommand>();    /**     * Map that holds the number of command sessions of each requester.     * Note: Key=requester full's JID, Value=number of sessions     */    private Map<String, AtomicInteger> sessionsCounter = new ConcurrentHashMap<String, AtomicInteger>();    /**     * Map that holds the command sessions. Used mainly to quickly locate a SessionData.     * Note: Key=sessionID, Value=SessionData     */    private Map<String, SessionData> sessions = new ConcurrentHashMap<String, SessionData>();    /**     * 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) {        commands.put(command.getCode(), 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.     * @return true if the requested command was removed from the list of available commands.     */    public boolean removeCommand(AdHocCommand command) {        return commands.remove(command.getCode()) != null;    }    /**     * Returns a list with the available commands in this command manager.     *     * @return a list with the available commands in this command manager.     */    public Collection<AdHocCommand> getCommands() {        return commands.values();    }    /**     * Returns the command whose code matches the specified code or <tt>null</tt> if none     * was found.     *     * @param code the code of the command to find.     * @return the command whose code matches the specified code or null if none     *         was found.     */    public AdHocCommand getCommand(String code) {        return commands.get(code);    }    public IQ process(IQ packet) {        IQ reply = IQ.createResultIQ(packet);        Element iqCommand = packet.getChildElement();        // Only packets of type SET can be processed        if (!IQ.Type.set.equals(packet.getType())) {            // Answer a bad_request error            reply.setChildElement(iqCommand.createCopy());            reply.setError(PacketError.Condition.bad_request);            return reply;        }        String sessionid = iqCommand.attributeValue("sessionid");        String commandCode = iqCommand.attributeValue("node");        String from = packet.getFrom().toString();        AdHocCommand command = commands.get(commandCode);        if (sessionid == null) {            // A new execution request has been received. Check that the command exists            if (command == null) {                // Requested command does not exist so return item_not_found error.                reply.setChildElement(iqCommand.createCopy());                reply.setError(PacketError.Condition.item_not_found);            }            else {                // Check that the requester has enough permission. Answer forbidden error if                // requester permissions are not enough to execute the requested command                if (!command.hasPermission(packet.getFrom())) {                    reply.setChildElement(iqCommand.createCopy());                    reply.setError(PacketError.Condition.forbidden);                    return reply;                }                // Create new session ID                sessionid = StringUtils.randomString(15);                Element childElement = reply.setChildElement("command", NAMESPACE);                if (command.getMaxStages(null) == 0) {                    // The command does not require any user interaction (returns results only)                    // Execute the command and return the execution result which may be a                    // data form (i.e. report data) or a note element                    command.execute(null, childElement);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.completed.name());                }                else {                    // The command requires user interactions (ie. has stages)                    // Check that the user has not excedded the limit of allowed simultaneous                    // command sessions.                    AtomicInteger counter = sessionsCounter.get(from);                    if (counter == null) {                        synchronized (from.intern()) {                            counter = sessionsCounter.get(from);                            if (counter == null) {                                counter = new AtomicInteger(0);                                sessionsCounter.put(from, counter);                            }                        }                    }                    int limit = JiveGlobals.getIntProperty("xmpp.command.limit", 100);                    if (counter.incrementAndGet() > limit) {                        counter.decrementAndGet();                        // Answer a not_allowed error since the user has exceeded limit. This                        // checking prevents bad users from consuming all the system memory by not                        // allowing them to create infinite simultaneous command sessions.                        reply.setChildElement(iqCommand.createCopy());                        reply.setError(PacketError.Condition.not_allowed);                        return reply;                    }                    // Originate a new command session.                    SessionData session = new SessionData(sessionid, packet.getFrom());                    sessions.put(sessionid, session);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.executing.name());                    // Add to the child element the data form the user must complete and                    // the allowed actions                    command.addNextStageInformation(session, childElement);                }            }        }        else {            // An execution session already exists and the user has requested to perform a            // certain action.            String action = iqCommand.attributeValue("action");            SessionData session = sessions.get(sessionid);            // Check that a Session exists for the specified sessionID            if (session == null) {                // Answer a bad_request error (bad-sessionid)                reply.setChildElement(iqCommand.createCopy());                reply.setError(PacketError.Condition.bad_request);                return reply;            }            // Check if the Session data has expired (default is 10 minutes)            int timeout = JiveGlobals.getIntProperty("xmpp.command.timeout", 10 * 60 * 1000);            if (System.currentTimeMillis() - session.getCreationStamp() > timeout) {                // TODO Check all sessions that might have timed out (use another thread?)                // Remove the old session                removeSessionData(sessionid, from);                // Answer a not_allowed error (session-expired)                reply.setChildElement(iqCommand.createCopy());                reply.setError(PacketError.Condition.not_allowed);                return reply;            }            synchronized (sessionid.intern()) {                // Check if the user is requesting to cancel the command                if (AdHocCommand.Action.cancel.name().equals(action)) {                    // User requested to cancel command execution so remove the session data                    removeSessionData(sessionid, from);                    // Generate a canceled confirmation response                    Element childElement = reply.setChildElement("command", NAMESPACE);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.canceled.name());                }                // If the user didn't specify an action then follow the default execute action                if (action == null || AdHocCommand.Action.execute.name().equals(action)) {                    action = session.getExecuteAction().name();                }                // Check that the specified action was previously offered                if (!session.isValidAction(action)) {                    // Answer a bad_request error (bad-action)                    reply.setChildElement(iqCommand.createCopy());                    reply.setError(PacketError.Condition.bad_request);                    return reply;                }                else if (AdHocCommand.Action.prev.name().equals(action)) {                    // Move to the previous stage and add to the child element the data form                    // the user must complete and the allowed actions of the previous stage                    Element childElement = reply.setChildElement("command", NAMESPACE);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.executing.name());                    command.addPreviousStageInformation(session, childElement);                }                else if (AdHocCommand.Action.next.name().equals(action)) {                    // Store the completed form in the session data                    saveCompletedForm(iqCommand, session);                    // Move to the next stage and add to the child element the new data form                    // the user must complete and the new allowed actions                    Element childElement = reply.setChildElement("command", NAMESPACE);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.executing.name());                    command.addNextStageInformation(session, childElement);                }                else if (AdHocCommand.Action.complete.name().equals(action)) {                    // Store the completed form in the session data                    saveCompletedForm(iqCommand, session);                    // Execute the command and return the execution result which may be a                    // data form (i.e. report data) or a note element                    Element childElement = reply.setChildElement("command", NAMESPACE);                    command.execute(session, childElement);                    childElement.addAttribute("sessionid", sessionid);                    childElement.addAttribute("node", commandCode);                    childElement.addAttribute("status", AdHocCommand.Status.completed.name());                    // Command has been executed so remove the session data                    removeSessionData(sessionid, from);                }            }        }        return reply;    }    /**     * Stores in the SessionData the fields and their values as specified in the completed     * data form by the user.     *     * @param iqCommand the command element containing the data form element.     * @param session the SessionData for this command execution.     */    private void saveCompletedForm(Element iqCommand, SessionData session) {        Element formElement = iqCommand.element(QName.get("x", "jabber:x:data"));        if (formElement != null) {            // Generate a Map with the variable names and variables values            Map<String, List<String>> data = new HashMap<String, List<String>>();            DataForm dataForm = new DataForm(formElement);            for (FormField field : dataForm.getFields()) {                data.put(field.getVariable(), field.getValues());            }            // Store the variables and their values in the session data            session.addStageForm(data);        }    }    /**     * Releases the data kept for the command execution whose id is sessionid. The number of     * commands executions currently being executed by the user (full JID) will be decreased.     *     * @param sessionid id of the session that identifies this command execution.     * @param from the full JID of the command requester.     */    private void removeSessionData(String sessionid, String from) {        sessions.remove(sessionid);        if (sessionsCounter.get(from).decrementAndGet() <= 0) {            // Remove the AtomicInteger when no commands are being executed            sessionsCounter.remove(from);        }    }    public void stop() {        // Cancel executions of running commands        sessions.clear();        sessionsCounter.clear();    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -