Search code examples
jsf-2resourcebundlefaces-config

enumerate resource-bundles defined in faces-config.xml


I am using a mojarra-specific code for this:

public static Map<String, ResourceBundle> getBundleMap()
{
    Locale locale = Faces.getLocale();

    ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance();
    Map<String, ApplicationResourceBundle> resourceBundles = associate.getResourceBundles();

    Map<String, ResourceBundle> map = new HashMap<>(resourceBundles.size());
    for(Entry<String, ApplicationResourceBundle> entry : resourceBundles.entrySet())
    {
        String name = entry.getKey();
        ResourceBundle bundle = entry.getValue().getResourceBundle(locale);

        map.put(name, bundle);
    }

    return map;
}

I'd like to have an implementation-agnostic way to get this map.

Should I parse every faces-config.xml defined in application and libs? Isn't this reinventing the wheel?

A Map<String, String>, where key = /faces-config/application/resource-bundle/var and value = /faces-config/application/resource-bundle/base-name would be sufficient.

Thanks.


Solution

  • I'd like to have an implementation-agnostic way to get this map.

    Understandable.


    Should I parse every faces-config.xml defined in application and libs?

    Yes. This functionality isn't available in JSF API.


    Isn't this reinventing the wheel?

    Yes, definitely. You could however try to get it into OmniFaces, which has already a similar utility class for /WEB-INF/web.xml and all /META-INF/web-fragment.xml, the WebXml.


    A Map<String, String>, where key = /faces-config/application/resource-bundle/var and value = /faces-config/application/resource-bundle/base-name would be sufficient.

    Here's a kickoff example using JAXP (cough):

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(false);
    factory.setNamespaceAware(false);
    factory.setExpandEntityReferences(false);
    
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document document = builder.newDocument();
    document.appendChild(document.createElement("all-faces-configs"));
    
    List<URL> facesConfigURLs = new ArrayList<>();
    facesConfigURLs.add(FacesContext.getCurrentInstance().getExternalContext().getResource("/WEB-INF/faces-config.xml"));
    facesConfigURLs.addAll(Collections.list(Thread.currentThread().getContextClassLoader().getResources("META-INF/faces-config.xml")));
    
    for (URL facesConfigURL : facesConfigURLs) {
        URLConnection connection = facesConfigURL.openConnection();
        connection.setUseCaches(false);
    
        try (InputStream input = connection.getInputStream()) {
            NodeList children = builder.parse(input).getDocumentElement().getChildNodes();
    
            for (int i = 0; i < children.getLength(); i++) {
                document.getDocumentElement().appendChild(document.importNode(children.item(i), true));
            }
        }
    }
    
    Map<String, String> resourceBundles = new HashMap<>();
    Element allFacesConfigs = document.getDocumentElement();
    XPath xpath = XPathFactory.newInstance().newXPath();
    NodeList resourceBundleNodes = (NodeList) xpath.compile("application/resource-bundle").evaluate(allFacesConfigs, XPathConstants.NODESET);
    
    for (int i = 0; i < resourceBundleNodes.getLength(); i++) {
        Node resourceBundleNode = resourceBundleNodes.item(i);
        String var = xpath.compile("var").evaluate(resourceBundleNode).trim();
        String baseName = xpath.compile("base-name").evaluate(resourceBundleNode).trim();
        resourceBundles.put(var, baseName);
    }