private DiscoInfoProvider getServerInfoProvider() {
        return new DiscoInfoProvider() {

            @Override
            public Iterator<Element> getIdentities(String name, String node, JID senderJID) {
                if (node != null && serverNodeProviders.get(node) != null) {
                    // Redirect the request to the disco info provider of the specified node
                    return serverNodeProviders.get(node).getIdentities(name, node, senderJID);
                }
                if (name == null || name.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
                    // Answer identity of the server itself.
                    final ArrayList<Element> identities = new ArrayList<>();
                    final Element identity = DocumentHelper.createElement("identity");
                    identity.addAttribute("category", "server");
                    identity.addAttribute("name", JiveGlobals.getProperty("xmpp.server.name", "Openfire Server"));
                    identity.addAttribute("type", "im");
                    identities.add(identity);

                    // Include identities from modules that implement ServerIdentitiesProvider
                    for (ServerIdentitiesProvider provider : serverIdentityProviders )
                    {
                        final Iterator<Element> iterator = provider.getIdentities();
                        while ( iterator.hasNext() )
                        {
                            identities.add( iterator.next() );
                        }
                    }
                    return identities.iterator();
                }
                else if (node != null) {
                    return XMPPServer.getInstance().getIQPEPHandler().getIdentities(name, node, senderJID);
                }
                else {
                    // Answer with identities of users of the server.
                    final Collection<UserIdentitiesProvider> providers;
                    if (SessionManager.getInstance().isAnonymousClientSession(name))
                    {
                        // Answer identity of an anonymous user.
                        providers = anonymousUserIdentityProviders;
                    }
                    else
                    {
                        // Answer identity of a registered user.
                        // Note: We know that this user exists because #hasInfo returned true
                        providers = registeredUserIdentityProviders;
                    }

                    final Set<Element> result = new HashSet<>();
                    for ( final UserIdentitiesProvider provider : providers )
                    {
                        final Iterator<Element> identities = provider.getIdentities();
                        while ( identities.hasNext() )
                        {
                            result.add( identities.next() );
                        }
                    }
                    return result.iterator();
                }
            }

            @Override
            public Iterator<String> getFeatures(String name, String node, JID senderJID) {
                if (node != null && serverNodeProviders.get(node) != null) {
                    // Redirect the request to the disco info provider of the specified node
                    return serverNodeProviders.get(node).getFeatures(name, node, senderJID);
                }
                if (name == null || name.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
                    // Answer features of the server itself.
                    final Set<String> result = new HashSet<>(serverFeatures.keySet());

                    if ( !UserManager.getInstance().isRegisteredUser( senderJID, false ) ) {
                        // Remove features not available to users from other servers or anonymous users.
                        // TODO this should be determined dynamically.
                        result.remove(IQPrivateHandler.NAMESPACE);
                        result.remove(IQBlockingHandler.NAMESPACE);
                    }
                    return result.iterator();
                }
                else if (node != null) {
                    return XMPPServer.getInstance().getIQPEPHandler().getFeatures(name, node, senderJID);
                }
                else {
                    // Answer with features of users of the server.
                    final Collection<UserFeaturesProvider> providers;
                    if (SessionManager.getInstance().isAnonymousClientSession(name))
                    {
                        // Answer features of an anonymous user.
                        providers = anonymousUserFeatureProviders;
                    }
                    else
                    {
                        // Answer features of a registered user.
                        // Note: We know that this user exists because #hasInfo returned true
                        providers = registeredUserFeatureProviders;
                    }
                    final Set<String> result = new HashSet<>();
                    for ( final UserFeaturesProvider provider : providers )
                    {
                        final Iterator<String> features = provider.getFeatures();
                        while ( features.hasNext() )
                        {
                            result.add( features.next() );
                        }
                    }
                    return result.iterator();
                }
            }

            @Override
            public boolean hasInfo(String name, String node, JID senderJID) throws UnauthorizedException
            {
                if (node != null) {
                    if (serverNodeProviders.get(node) != null) {
                        // Redirect the request to the disco info provider of the specified node
                        return serverNodeProviders.get(node).hasInfo(name, node, senderJID);
                    }
                    if (name != null) {
                        return XMPPServer.getInstance().getIQPEPHandler().hasInfo(name, node, senderJID);
                    }
                    // Unknown node
                    return false;
                }

                // XEP-0030, Section 8 "Security Considerations": <blockquote>The following rules apply to the handling of
                // service discovery requests sent to bare JIDs: In response to a disco#info request, the server MUST return
                // a <service-unavailable/> error if [...] The requesting entity is not authorized to receive presence from the
                // target entity (i.e., via the target having a presence subscription to the requesting entity of type "both" or
                // "from") or is not otherwise trusted (e.g., another server in a trusted network).</blockquote>
                boolean isRequestingEntityAuthorized;

                if (name == null || name.equals(senderJID.getNode())) {
                    // Entities are always authorized when querying themselves.
                    isRequestingEntityAuthorized = true;
                } else {
                    // when the target entity is an end-user, check for presence subscription state.
                    try {
                        final User user = UserManager.getInstance().getUser(name);
                        RosterItem item = user.getRoster().getRosterItem(senderJID);
                        isRequestingEntityAuthorized = item.getSubStatus() == RosterItem.SUB_FROM || item.getSubStatus() == RosterItem.SUB_BOTH;
                    } catch (UserNotFoundException e) {
                        // Not an existing user or no subscription. Response should be indistinguishable from response to a
                        // non-subscribed user.
                        isRequestingEntityAuthorized = false;
                    }
                }

                if (!isRequestingEntityAuthorized) {
                    throw new UnauthorizedException();
                }

                return true;
            }

            @Override
            public Set<DataForm> getExtendedInfos(String name, String node, JID senderJID) {
                if (node != null && serverNodeProviders.get(node) != null) {
                    // Redirect the request to the disco info provider of the specified node
                    return serverNodeProviders.get(node).getExtendedInfos(name, node, senderJID);
                }
                if (name == null || name.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
                    // Answer extended info of the server itself.

                    // XEP-0157 Contact addresses for XMPP Services
                    if ( !JiveGlobals.getBooleanProperty( "admin.disable-exposure" ) )
                    {
                        final Collection<JID> admins = XMPPServer.getInstance().getAdmins();
                        if ( admins == null || admins.isEmpty() )
                        {
                            return null;
                        }

                        final DataForm dataForm = new DataForm(DataForm.Type.result);

                        final FormField fieldType = dataForm.addField();
                        fieldType.setVariable("FORM_TYPE");
                        fieldType.setType(FormField.Type.hidden);
                        fieldType.addValue("http://jabber.org/network/serverinfo");

                        final FormField fieldAdminAddresses = dataForm.addField();
                        fieldAdminAddresses.setVariable("admin-addresses");
                        fieldAdminAddresses.setType(Type.list_multi);

                        final UserManager userManager = UserManager.getInstance();
                        for ( final JID admin : admins )
                        {
                            fieldAdminAddresses.addValue( "xmpp:" + admin.asBareJID() );
                            if ( admin.getDomain().equals( XMPPServer.getInstance().getServerInfo().getXMPPDomain() ) ) {
                                try
                                {
                                    final String email = userManager.getUser( admin.getNode() ).getEmail();
                                    if ( email != null && !email.trim().isEmpty() )
                                    {
                                        fieldAdminAddresses.addValue( "mailto:" + email );
                                    }
                                }
                                catch (Exception e)
                                {
                                    continue;
                                }
                            }
                        }

                        //XEP-0232 includes extended information about Software Version in a data form
                        final DataForm dataFormSoftwareVersion = new DataForm(DataForm.Type.result);

                        final FormField fieldTypeSoftwareVersion = dataFormSoftwareVersion.addField();
                        fieldTypeSoftwareVersion.setVariable("FORM_TYPE");
                        fieldTypeSoftwareVersion.setType(FormField.Type.hidden);
                        fieldTypeSoftwareVersion.addValue("urn:xmpp:dataforms:softwareinfo");

                        final FormField fieldOs = dataFormSoftwareVersion.addField();
                        fieldOs.setType(Type.text_single);
                        fieldOs.setVariable("os");
                        fieldOs.addValue( System.getProperty("os.name"));

                        final FormField fieldOsVersion = dataFormSoftwareVersion.addField();
                        fieldOsVersion.setType(Type.text_single);
                        fieldOsVersion.setVariable("os_version");
                        fieldOsVersion.addValue(System.getProperty("os.version")+" "+System.getProperty("os.arch")+" - Java " + System.getProperty("java.version"));

                        final FormField fieldSoftware = dataFormSoftwareVersion.addField();
                        fieldSoftware.setType(Type.text_single);
                        fieldSoftware.setVariable("software");
                        fieldSoftware.addValue(AdminConsole.getAppName());

                        final FormField fieldSoftwareVersion = dataFormSoftwareVersion.addField();
                        fieldSoftwareVersion.setType(Type.text_single);
                        fieldSoftwareVersion.setVariable("software_version");
                        fieldSoftwareVersion.addValue(AdminConsole.getVersionString());

                        final Set<DataForm> dataForms = new HashSet<>();
                        if (ENABLED.getValue()){
                            dataForms.add(dataFormSoftwareVersion);
                        }
                        dataForms.add(dataForm);
                        return dataForms;
                    }
                }
                if (node != null && name != null) {
                    return XMPPServer.getInstance().getIQPEPHandler().getExtendedInfos(name, node, senderJID);
                }
                return Collections.emptySet();
            }
        };
    }
Returns the DiscoInfoProvider responsible for providing information at the server level. This
means that this DiscoInfoProvider will provide information whenever a disco request whose
recipient JID is the server (e.g. localhost) is made.

@return the DiscoInfoProvider responsible for providing information at the server level.
xmppserver/src/main/java/org/jivesoftware/openfire/disco/IQDiscoInfoHandler.java