org.sipfoundry.sipxconfig.site.common.JarMessagesSource.java Source code

Java tutorial

Introduction

Here is the source code for org.sipfoundry.sipxconfig.site.common.JarMessagesSource.java

Source

/*
 *
 *
 * Copyright (C) 2007 Pingtel Corp., certain elements licensed under a Contributor Agreement.
 * Contributors retain copyright to elements licensed under a Contributor Agreement.
 * Licensed to the User under the LGPL license.
 *
 *
 */
package org.sipfoundry.sipxconfig.site.common;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.Messages;
import org.apache.hivemind.Resource;
import org.apache.hivemind.util.FileResource;
import org.apache.hivemind.util.LocalizedNameGenerator;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.services.impl.ComponentMessages;

public class JarMessagesSource implements LanguageSupport {
    private static final String LOCALE_PROPERTY = "locale";
    private static final String WEB_INF_STRING = "WEB-INF";
    private static final Log LOG = LogFactory.getLog(JarMessagesSource.class);
    private static final Resource LANGUAGE_NAME_RESOURCE = new FileResource(
            "context:/WEB-INF/admin/language.properties");
    private JarMessagesSourceContext m_context;
    private URLClassLoader m_jarClassLoader;
    private Map<Locale, Properties> m_globalProps = new HashMap<Locale, Properties>();
    private String m_globalFile = "WEB-INF/sipXconfig-web_%s.properties";

    public void setContext(JarMessagesSourceContext context) {
        m_context = context;
    }

    public Messages getMessages(IComponent component) {
        Properties messageProperties = loadMessagesFromJar(component);
        if (messageProperties == null) {
            return null;
        }
        return new ComponentMessages(component.getPage().getLocale(), messageProperties);
    }

    public String resolveLocaleName(String localeString) {
        Locale locale = null;
        String[] localeStrings = localeString.split("-");
        if (localeStrings.length == 1) {
            locale = new Locale(localeStrings[0]);
        } else if (localeStrings.length == 2) {
            locale = new Locale(localeStrings[0], localeStrings[1]);
        } else if (localeStrings.length == 3) {
            locale = new Locale(localeStrings[0], localeStrings[1], localeStrings[2]);
        }

        return resolveLocaleName(locale);
    }

    public String resolveLocaleName(Locale locale) {
        Properties languagesForLocale = loadMessagesFromJar(LANGUAGE_NAME_RESOURCE, locale);
        if (languagesForLocale == null || languagesForLocale.getProperty(LOCALE_PROPERTY) == null) {
            return locale.getDisplayName(locale);
        }
        return languagesForLocale.getProperty(LOCALE_PROPERTY);
    }

    private Properties loadMessagesFromJar(Resource resource, Locale locale) {
        if (m_jarClassLoader == null) {
            try {
                initializeClassLoader();
            } catch (IOException ioe) {
                LOG.error("Error initializing messages class loader.", ioe);
                return null;
            }
        }

        String resourceName = resource.getName();
        String basename = StringUtils.substringBeforeLast(resourceName, ".");
        LocalizedNameGenerator localizedNameGenerator = new LocalizedNameGenerator(basename, locale, ".properties");

        List<Resource> localizedNameList = new ArrayList<Resource>();
        while (localizedNameGenerator.more()) {
            String localizedName = localizedNameGenerator.next();
            localizedNameList.add(resource.getRelativeResource(localizedName));
        }

        InputStream stream = null;
        for (Resource eachResource : localizedNameList) {
            String resourcePath = eachResource.getPath();

            // only handle resource paths that contain "WEB-INF"/ (i.e. part of
            // the sipXconfig web app
            if (!resourcePath.contains(WEB_INF_STRING)) {
                continue;
            }

            // strip off any portion of the resource path preceding "WEB-INF"
            // in order to load the correct messages
            String contextPath = resourcePath.substring(resourcePath.indexOf(WEB_INF_STRING));
            stream = m_jarClassLoader.getResourceAsStream(contextPath);

            // once we are able to load a stream for a resource, exit loop
            if (stream != null) {
                break;
            }
        }

        if (stream == null) {
            return null;
        }

        Properties messages = new Properties();
        try {
            messages.load(stream);
        } catch (IOException ioe) {
            LOG.error("Error loading localized messages.", ioe);
            return null;
        } finally {
            IOUtils.closeQuietly(stream);
        }

        if (m_globalProps.get(locale) == null) {
            Properties globalMessages = new Properties();
            try {
                String globalFile = String.format(m_globalFile, locale.getLanguage());
                stream = m_jarClassLoader.getResourceAsStream(globalFile);
                if (stream != null) {
                    globalMessages.load(stream);
                }
                m_globalProps.put(locale, globalMessages);
            } catch (IOException ioe) {
                LOG.error("Error loading global localized messages", ioe);
            } finally {
                IOUtils.closeQuietly(stream);
            }
        }
        messages.putAll(m_globalProps.get(locale));

        return messages;
    }

    private Properties loadMessagesFromJar(IComponent component) {
        Resource specificationLocation = component.getSpecification().getSpecificationLocation();
        return loadMessagesFromJar(specificationLocation, component.getPage().getLocale());
    }

    private void initializeClassLoader() throws IOException {
        if (m_context == null) {
            throw new IllegalStateException("Context must be set.");
        }
        File localizationPackageRootDir = new File(m_context.getLocalizationPackageRoot());
        File[] jarFiles = localizationPackageRootDir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.matches("sipxconfig_[a-zA-Z]{2}(\\-[a-zA-Z0-9]{2,}){0,1}\\.jar");
            }
        });
        URL[] jarUrls = new URL[jarFiles.length];
        for (int i = 0; i < jarFiles.length; i++) {
            jarUrls[i] = jarFiles[i].toURL();
        }

        m_jarClassLoader = new URLClassLoader(jarUrls);
    }
}