undertow/src/main/java/org/wildfly/extension/undertow/security/jacc/WarJACCService.java
static HashMap<String, PatternInfo> qualifyURLPatterns(JBossWebMetaData metaData) {
        ArrayList<PatternInfo> prefixList = new ArrayList<PatternInfo>();
        ArrayList<PatternInfo> extensionList = new ArrayList<PatternInfo>();
        ArrayList<PatternInfo> exactList = new ArrayList<PatternInfo>();
        HashMap<String, PatternInfo> patternMap = new HashMap<String, PatternInfo>();
        PatternInfo defaultInfo = null;

        List<SecurityConstraintMetaData> constraints = metaData.getSecurityConstraints();
        if (constraints != null) {
            for (SecurityConstraintMetaData constraint : constraints) {
                WebResourceCollectionsMetaData resourceCollectionsMetaData = constraint.getResourceCollections();
                if (resourceCollectionsMetaData != null) {
                    for (WebResourceCollectionMetaData resourceCollectionMetaData : resourceCollectionsMetaData) {
                        List<String> urlPatterns = resourceCollectionMetaData.getUrlPatterns();
                        for (String url : urlPatterns) {
                            int type = getPatternType(url);
                            PatternInfo info = patternMap.get(url);
                            if (info == null) {
                                info = new PatternInfo(url, type);
                                patternMap.put(url, info);
                                switch (type) {
                                    case PREFIX:
                                        prefixList.add(info);
                                        break;
                                    case EXTENSION:
                                        extensionList.add(info);
                                        break;
                                    case EXACT:
                                        exactList.add(info);
                                        break;
                                    case DEFAULT:
                                        defaultInfo = info;
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }
        JBossServletsMetaData servlets = metaData.getServlets();
        List<ServletMappingMetaData> mappings = metaData.getServletMappings();
        if(!metaData.isMetadataComplete() && servlets != null && mappings != null) {

            Map<String, List<String>> servletMappingMap = new HashMap<>();
            for(ServletMappingMetaData mapping : mappings) {
                List<String> list = servletMappingMap.get(mapping.getServletName());
                if(list == null) {
                    servletMappingMap.put(mapping.getServletName(), list = new ArrayList<>());
                }
                list.addAll(mapping.getUrlPatterns());
            }
            for (JBossServletMetaData servlet : servlets) {
                ServletSecurityMetaData security = servlet.getServletSecurity();
                if(security != null) {
                    List<String> servletMappings = servletMappingMap.get(servlet.getServletName());
                    if(servletMappings != null) {
                        for (String url : servletMappings) {
                            int type = getPatternType(url);
                            PatternInfo info = patternMap.get(url);
                            if (info == null) {
                                info = new PatternInfo(url, type);
                                patternMap.put(url, info);
                                switch (type) {
                                    case PREFIX:
                                        prefixList.add(info);
                                        break;
                                    case EXTENSION:
                                        extensionList.add(info);
                                        break;
                                    case EXACT:
                                        exactList.add(info);
                                        break;
                                    case DEFAULT:
                                        defaultInfo = info;
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }

        // Qualify all prefix patterns
        for (int i = 0; i < prefixList.size(); i++) {
            PatternInfo info = prefixList.get(i);
            // Qualify by every other prefix pattern matching this pattern
            for (int j = 0; j < prefixList.size(); j++) {
                if (i == j)
                    continue;
                PatternInfo other = prefixList.get(j);
                if (info.matches(other))
                    info.addQualifier(other);
            }
            // Qualify by every exact pattern that is matched by this pattern
            for (PatternInfo other : exactList) {
                if (info.matches(other))
                    info.addQualifier(other);
            }
        }

        // Qualify all extension patterns
        for (PatternInfo info : extensionList) {
            // Qualify by every path prefix pattern
            for (PatternInfo other : prefixList) {
                // Any extension
                info.addQualifier(other);
            }
            // Qualify by every matching exact pattern
            for (PatternInfo other : exactList) {
                if (info.isExtensionFor(other))
                    info.addQualifier(other);
            }
        }

        // Qualify the default pattern
        if (defaultInfo == null) {
            defaultInfo = new PatternInfo("/", DEFAULT);
            patternMap.put("/", defaultInfo);
        }
        for (PatternInfo info : patternMap.values()) {
            if (info == defaultInfo)
                continue;
            defaultInfo.addQualifier(info);
        }

        return patternMap;
    }
static HashMap<String, PatternInfo> qualifyURLPatterns(JBossWebMetaData metaData) {
        ArrayList<PatternInfo> prefixList = new ArrayList<PatternInfo>();
        ArrayList<PatternInfo> extensionList = new ArrayList<PatternInfo>();
        ArrayList<PatternInfo> exactList = new ArrayList<PatternInfo>();
        HashMap<String, PatternInfo> patternMap = new HashMap<String, PatternInfo>();
        PatternInfo defaultInfo = null;

        List<SecurityConstraintMetaData> constraints = metaData.getSecurityConstraints();
        if (constraints != null) {
            for (SecurityConstraintMetaData constraint : constraints) {
                WebResourceCollectionsMetaData resourceCollectionsMetaData = constraint.getResourceCollections();
                if (resourceCollectionsMetaData != null) {
                    for (WebResourceCollectionMetaData resourceCollectionMetaData : resourceCollectionsMetaData) {
                        List<String> urlPatterns = resourceCollectionMetaData.getUrlPatterns();
                        for (String url : urlPatterns) {
                            int type = getPatternType(url);
                            PatternInfo info = patternMap.get(url);
                            if (info == null) {
                                info = new PatternInfo(url, type);
                                patternMap.put(url, info);
                                switch (type) {
                                    case PREFIX:
                                        prefixList.add(info);
                                        break;
                                    case EXTENSION:
                                        extensionList.add(info);
                                        break;
                                    case EXACT:
                                        exactList.add(info);
                                        break;
                                    case DEFAULT:
                                        defaultInfo = info;
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }
        JBossServletsMetaData servlets = metaData.getServlets();
        List<ServletMappingMetaData> mappings = metaData.getServletMappings();
        if(!metaData.isMetadataComplete() && servlets != null && mappings != null) {

            Map<String, List<String>> servletMappingMap = new HashMap<>();
            for(ServletMappingMetaData mapping : mappings) {
                List<String> list = servletMappingMap.get(mapping.getServletName());
                if(list == null) {
                    servletMappingMap.put(mapping.getServletName(), list = new ArrayList<>());
                }
                list.addAll(mapping.getUrlPatterns());
            }
            for (JBossServletMetaData servlet : servlets) {
                ServletSecurityMetaData security = servlet.getServletSecurity();
                if(security != null) {
                    List<String> servletMappings = servletMappingMap.get(servlet.getServletName());
                    if(servletMappings != null) {
                        for (String url : servletMappings) {
                            int type = getPatternType(url);
                            PatternInfo info = patternMap.get(url);
                            if (info == null) {
                                info = new PatternInfo(url, type);
                                patternMap.put(url, info);
                                switch (type) {
                                    case PREFIX:
                                        prefixList.add(info);
                                        break;
                                    case EXTENSION:
                                        extensionList.add(info);
                                        break;
                                    case EXACT:
                                        exactList.add(info);
                                        break;
                                    case DEFAULT:
                                        defaultInfo = info;
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }

        // Qualify all prefix patterns
        for (int i = 0; i < prefixList.size(); i++) {
            PatternInfo info = prefixList.get(i);
            // Qualify by every other prefix pattern matching this pattern
            for (int j = 0; j < prefixList.size(); j++) {
                if (i == j)
                    continue;
                PatternInfo other = prefixList.get(j);
                if (info.matches(other))
                    info.addQualifier(other);
            }
            // Qualify by every exact pattern that is matched by this pattern
            for (PatternInfo other : exactList) {
                if (info.matches(other))
                    info.addQualifier(other);
            }
        }

        // Qualify all extension patterns
        for (PatternInfo info : extensionList) {
            // Qualify by every path prefix pattern
            for (PatternInfo other : prefixList) {
                // Any extension
                info.addQualifier(other);
            }
            // Qualify by every matching exact pattern
            for (PatternInfo other : exactList) {
                if (info.isExtensionFor(other))
                    info.addQualifier(other);
            }
        }

        // Qualify the default pattern
        if (defaultInfo == null) {
            defaultInfo = new PatternInfo("/", DEFAULT);
            patternMap.put("/", defaultInfo);
        }
        for (PatternInfo info : patternMap.values()) {
            if (info == defaultInfo)
                continue;
            defaultInfo.addQualifier(info);
        }

        return patternMap;
    }
JACC url pattern Qualified URL Pattern Names.

The rules for qualifying a URL pattern are dependent on the rules for determining if one URL pattern matches another as
defined in Section 3.1.3.3, Servlet URL-Pattern Matching Rules, and are described as follows: - If the pattern is a path
prefix pattern, it must be qualified by every path-prefix pattern in the deployment descriptor matched by and different
from the pattern being qualified. The pattern must also be qualified by every exact pattern appearing in the deployment
descriptor that is matched by the pattern being qualified. - If the pattern is an extension pattern, it must be qualified
by every path-prefix pattern appearing in the deployment descriptor and every exact pattern in the deployment descriptor
that is matched by the pattern being qualified. - If the pattern is the default pattern, "/", it must be qualified by
every other pattern except the default pattern appearing in the deployment descriptor. - If the pattern is an exact
pattern, its qualified form must not contain any qualifying patterns.

URL patterns are qualified by appending to their String representation, a colon separated representation of the list of
patterns that qualify the pattern. Duplicates must not be included in the list of qualifying patterns, and any qualifying
pattern matched by another qualifying pattern may5 be dropped from the list.

Any pattern, qualified by a pattern that matches it, is overridden and made irrelevant (in the translation) by the
qualifying pattern. Specifically, all extension patterns and the default pattern are made irrelevant by the presence of
the path prefix pattern "/*" in a deployment descriptor. Patterns qualified by the "/*" pattern violate the
URLPatternSpec constraints of WebResourcePermission and WebUserDataPermission names and must be rejected by the
corresponding permission constructors.

@param metaData - the web deployment metadata
@return HashMap<String, PatternInfo>