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;
    /**
     * Manager that keeps the list of ad-hoc commands and processing command requests.
     */
    private AdHocCommandManager manager;

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

    @Override
    public IQ handleIQ(IQ packet) throws UnauthorizedException {
        return manager.process(packet);
    }

    @Override
    public IQHandlerInfo getInfo() {
        return info;
    }

    @Override
    public Iterator<String> getFeatures() {
        return Collections.singleton(NAMESPACE).iterator();
    }

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

    @Override
    public Iterator<String> getFeatures(String name, String node, JID senderJID) {
        return Arrays.asList(NAMESPACE, "jabber:x:data").iterator();
    }
    
    @Override
    public Set<DataForm> getExtendedInfos(String name, String node, JID senderJID) {
        return new HashSet<>();
    }

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

    @Override
    public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
        List<DiscoItem> answer = new ArrayList<>();
        if (!NAMESPACE.equals(node)) {
            answer = Collections.emptyList();
        }
        else {
            for (AdHocCommand command : manager.getCommands()) {
                // Only include commands that the sender can invoke (i.e. has enough permissions)
                if (command.hasPermission(senderJID)) {
                    final DiscoItem item = new DiscoItem(new JID(serverName),
                            command.getLabel(), command.getCode(), null);
                    answer.add(item);
                }
            }
        }
        return answer.iterator();
    }

    @Override
    public void initialize(XMPPServer server) {
        super.initialize(server);
        serverName = server.getServerInfo().getXMPPDomain();
        infoHandler = server.getIQDiscoInfoHandler();
        itemsHandler = server.getIQDiscoItemsHandler();
    }

    @Override
    public void start() throws IllegalStateException {
        super.start();
        infoHandler.setServerNodeInfoProvider(NAMESPACE, this);
        itemsHandler.setServerNodeInfoProvider(NAMESPACE, this);
        // Add the "out of the box" commands
        addDefaultCommands();
    }

    @Override
    public void stop() {
        super.stop();
        infoHandler.removeServerNodeInfoProvider(NAMESPACE);
        itemsHandler.removeServerNodeInfoProvider(NAMESPACE);
        // Stop commands
        for (AdHocCommand command : manager.getCommands()) {
            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) {
        manager.addCommand(command);
        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) {
        if (manager.removeCommand(command)) {
            stopCommand(command);
        }
    }

    private void addDefaultCommands() {<FILL_FUNCTION_BODY>}

    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());
    }
}

        addCommand(new EditAdminList());
        addCommand(new GetNumberRegisteredUsers());
        addCommand(new GetNumberDisabledUsers());
        addCommand(new GetNumberActiveUsers());
        addCommand(new GetNumberOnlineUsers());
        addCommand(new GetNumberIdleUsers());
        addCommand(new GetNumberUserSessions());
        addCommand(new GetListRegisteredUsers());
        addCommand(new GetListActiveUsers());
        addCommand(new GetListDisabledUsers());
        addCommand(new GetListOnlineUsers());
        addCommand(new GetUsersPresence());
        addCommand(new GetListGroups());
        addCommand(new GetListGroupUsers());
        addCommand(new AddGroupUsers());
        addCommand(new DeleteGroupUsers());
        addCommand(new AddGroup());
        addCommand(new UpdateGroup());
        addCommand(new DeleteGroup());
        addCommand(new AddUser());
        addCommand(new DeleteUser());
        addCommand(new DisableUser());
        addCommand(new ReEnableUser());
        addCommand(new EndUserSession());
        addCommand(new GetUserRoster());
        addCommand(new AuthenticateUser());
        addCommand(new ChangeUserPassword());
        addCommand(new UserProperties());
        addCommand(new PacketsNotification());
        addCommand(new GetServerStats());
        addCommand(new HttpBindStatus());
        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());
        addCommand(new GetAdminConsoleInfo());
        addCommand(new Ping());
        addCommand(new EditBlockedList());
        addCommand(new EditAllowedList());
        addCommand(new SendAnnouncementToOnlineUsers());
    
<methods>public void <init>(java.lang.String) ,public abstract org.jivesoftware.openfire.IQHandlerInfo getInfo() ,public abstract IQ handleIQ(IQ) throws org.jivesoftware.openfire.auth.UnauthorizedException,public void initialize(org.jivesoftware.openfire.XMPPServer) ,public boolean performNoSuchUserCheck() ,public void process(Packet) throws org.jivesoftware.openfire.PacketException<variables>private static final Logger Log,protected org.jivesoftware.openfire.PacketDeliverer deliverer,protected org.jivesoftware.openfire.SessionManager sessionManager