private void loadExtensions(Collection<Resource> javaScriptResources,
            Collection<Resource> cssResources,
            Set<String> toleratedAuthProviders) {

        // Advise of current extension load order and how the order may be
        // changed
        List<Extension> extensions = getExtensions();
        if (extensions.size() > 1) {
            logger.info("Multiple extensions are installed and will be "
                    + "loaded in order of decreasing priority:");

            for (Extension extension : extensions) {
                logger.info(" - [{}] \"{}\" ({})", extension.getNamespace(),
                        extension.getName(), extension.getFile());
            }

            logger.info("To change this order, set the \"{}\" property or "
                    + "rename the extension files. The default priority of "
                    + "extensions is dictated by the sort order of their "
                    + "filenames.", EXTENSION_PRIORITY.getName());
        }

        // Load all extensions
        for (Extension extension : extensions) {

            // Add any JavaScript / CSS resources
            javaScriptResources.addAll(extension.getJavaScriptResources().values());
            cssResources.addAll(extension.getCSSResources().values());

            // Attempt to load all authentication providers
            bindAuthenticationProviders(extension.getAuthenticationProviderClasses(), toleratedAuthProviders);

            // Attempt to load all listeners
            bindListeners(extension.getListenerClasses());

            // Add any translation resources
            serveLanguageResources(extension.getTranslationResources());

            // Add all HTML patch resources
            patchResourceService.addPatchResources(extension.getHTMLResources().values());

            // Add all static resources under namespace-derived prefix
            String staticResourcePrefix = "/app/ext/" + extension.getNamespace() + "/";
            serveStaticResources(staticResourcePrefix, extension.getStaticResources());

            // Serve up the small favicon if provided
            if(extension.getSmallIcon() != null)
                serve("/images/logo-64.png").with(new ResourceServlet(extension.getSmallIcon()));

            // Serve up the large favicon if provided
            if(extension.getLargeIcon()!= null)
                serve("/images/logo-144.png").with(new ResourceServlet(extension.getLargeIcon()));

            // Log successful loading of extension by name
            logger.info("Extension \"{}\" ({}) loaded.", extension.getName(), extension.getNamespace());

        }

    }
Loads all extensions within the GUACAMOLE_HOME/extensions directory, if
any, adding their static resource to the given resource collections.

@param javaScriptResources
    A modifiable collection of static JavaScript resources which may
    receive new JavaScript resources from extensions.

@param cssResources
    A modifiable collection of static CSS resources which may receive
    new CSS resources from extensions.

@param toleratedAuthProviders
    The set of identifiers of all authentication providers whose
    internal failures should be tolerated during the authentication
    process. If the identifier of an authentication provider is within
    this set, errors during authentication will result in the
    authentication provider being ignored for that authentication
    attempt, with the authentication process proceeding as if that
    authentication provider were not present. By default, errors during
    authentication halt the authentication process entirely.
guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java