Package org.apache.felix.inventory.impl.webconsole

Source Code of org.apache.felix.inventory.impl.webconsole.ResourceBundleManager

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.inventory.impl.webconsole;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;

/**
* The ResourceBundleManager manages resource bundle instance per OSGi Bundle.
* It contains a local cache, for bundles, but when a bundle is being
* unistalled,
* its resources stored in the cache are cleaned up.
*/
public class ResourceBundleManager implements BundleListener
{

    private final BundleContext bundleContext;

    private final Map resourceBundleCaches;

    /**
     * Creates a new object and adds self as a bundle listener
     *
     * @param bundleContext the bundle context of the Web Console.
     */
    public ResourceBundleManager(final BundleContext bundleContext)
    {
        this.bundleContext = bundleContext;
        this.resourceBundleCaches = new HashMap();

        bundleContext.addBundleListener(this);
    }

    /**
     * Removes the bundle lister.
     */
    public void dispose()
    {
        bundleContext.removeBundleListener(this);
    }

    /**
     * This method is used to retrieve a /cached/ instance of the i18n resource
     * associated
     * with a given bundle.
     *
     * @param provider the bundle, provider of the resources
     * @param locale the requested locale.
     */
    public ResourceBundle getResourceBundle(final Bundle provider)
    {
        ResourceBundle cache;
        final Long key = new Long(provider.getBundleId());
        synchronized (resourceBundleCaches)
        {
            cache = (ResourceBundle) resourceBundleCaches.get(key);
            if (cache == null && !resourceBundleCaches.containsKey(key))
            {
                cache = this.loadResourceBundle(provider);
                resourceBundleCaches.put(key, cache);
            }
        }

        return cache;
    }

    // ---------- BundleListener

    /**
     * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
     */
    public final void bundleChanged(BundleEvent event)
    {
        if (event.getType() == BundleEvent.STOPPED)
        {
            final Long key = new Long(event.getBundle().getBundleId());
            synchronized (resourceBundleCaches)
            {
                resourceBundleCaches.remove(key);
            }
        }
    }

    private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;

    private ResourceBundle loadResourceBundle(final Bundle bundle)
    {
        final String path = "_" + DEFAULT_LOCALE.toString(); //$NON-NLS-1$
        final URL source = (URL) getResourceBundleEntries(bundle).get(path);
        if (source != null)
        {
            try
            {
                return new PropertyResourceBundle(source.openStream());
            }
            catch (final IOException ignore)
            {
                // ignore
            }
        }
        return null;
    }

    // TODO : Instead of getting all property files, we could just get the one
    // for the default locale
    private synchronized Map getResourceBundleEntries(final Bundle bundle)
    {
        String file = (String) bundle.getHeaders().get(Constants.BUNDLE_LOCALIZATION);
        if (file == null)
        {
            file = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
        }

        // remove leading slash
        if (file.startsWith("/")) //$NON-NLS-1$
        {
            file = file.substring(1);
        }

        // split path and base name
        int slash = file.lastIndexOf('/');
        String fileName = file.substring(slash + 1);
        String path = (slash <= 0) ? "/" : file.substring(0, slash); //$NON-NLS-1$

        HashMap resourceBundleEntries = new HashMap();

        Enumeration locales = bundle.findEntries(path, fileName + "*.properties", false); //$NON-NLS-1$
        if (locales != null)
        {
            while (locales.hasMoreElements())
            {
                URL entry = (URL) locales.nextElement();

                // calculate the key
                String entryPath = entry.getPath();
                final int start = entryPath.lastIndexOf('/') + 1 + fileName.length(); // path,
                                                                                      // slash
                                                                                      // and
                                                                                      // base
                                                                                      // name
                final int end = entryPath.length() - 11; // .properties suffix
                entryPath = entryPath.substring(start, end);

                // the default language is "name.properties" thus the entry
                // path is empty and must default to "_"+DEFAULT_LOCALE
                if (entryPath.length() == 0)
                {
                    entryPath = "_" + DEFAULT_LOCALE; //$NON-NLS-1$
                }

                // only add this entry, if the "language" is not provided
                // by the main bundle or an earlier bound fragment
                if (!resourceBundleEntries.containsKey(entryPath))
                {
                    resourceBundleEntries.put(entryPath, entry);
                }
            }
        }

        return resourceBundleEntries;
    }
}
TOP

Related Classes of org.apache.felix.inventory.impl.webconsole.ResourceBundleManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.