org.jabylon.rest.ui.model.OSGiAwareBundleStringResourceLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.jabylon.rest.ui.model.OSGiAwareBundleStringResourceLoader.java

Source

/**
 * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.jabylon.rest.ui.model;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;
import java.util.concurrent.ExecutionException;

import org.apache.wicket.Component;
import org.apache.wicket.Session;
import org.apache.wicket.resource.loader.IStringResourceLoader;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class OSGiAwareBundleStringResourceLoader implements IStringResourceLoader {

    private final BundleContext context;
    private LoadingCache<Integer, ClassLoader> cache;
    private Logger logger = LoggerFactory.getLogger(OSGiAwareBundleStringResourceLoader.class);
    /**
     * to make sure it always reverts to the base bundle instead of the system default locale
     */
    private static final Control CONTROL = ResourceBundle.Control.getNoFallbackControl(Control.FORMAT_PROPERTIES);

    public OSGiAwareBundleStringResourceLoader() {
        context = FrameworkUtil.getBundle(getClass()).getBundleContext();
        cache = CacheBuilder.newBuilder().build(new CacheLoader<Integer, ClassLoader>() {

            @Override
            public ClassLoader load(Integer key) throws Exception {
                Bundle bundle = context.getBundle(key);
                String bundleName = bundle.getHeaders().get("Bundle-Localisation");
                if (bundleName == null)
                    bundleName = "OSGI-INF/l10n/bundle";
                String prefix = "/" + bundleName.substring(0, bundleName.lastIndexOf('/'));
                Enumeration<URL> entries = bundle.findEntries(prefix, "*.properties", false);
                List<URL> urls = Collections.emptyList();
                if (entries != null) {
                    urls = new ArrayList<URL>();
                    while (entries.hasMoreElements()) {
                        URL url = entries.nextElement();
                        urls.add(url);
                    }
                }
                return new BundleClassloader(prefix, urls);
            }

        });
    }

    @Override
    public final String loadStringResource(final Class<?> clazz, final String key, Locale locale,
            final String style, final String variation) {
        try {
            if (key.startsWith("%")) {
                if (locale == null) {
                    locale = Session.exists() ? Session.get().getLocale() : Locale.getDefault();
                }
                int keyStart = key.indexOf("|");
                int bundleId = Integer.parseInt(key.substring(1, keyStart));
                Bundle bundle = context.getBundle(bundleId);
                String bundleName = bundle.getHeaders().get("Bundle-Localisation");
                if (bundleName == null)
                    bundleName = "OSGI-INF/l10n/bundle";

                return ResourceBundle.getBundle(bundleName, locale, cache.get(bundleId), CONTROL)
                        .getString(key.substring(keyStart + 1));
            } else if (key.startsWith("|")) {
                //starts with a marker that this key is to be treated as the value
                return key.substring(1);
            }
            return null;
        } catch (MissingResourceException e) {
            return null;
        } catch (ExecutionException e) {
            logger.warn("Failed to create classloader for key " + key, e);
            return null;
        }
    }

    @Override
    public final String loadStringResource(final Component component, final String key, Locale locale,
            final String style, final String variation) {
        return loadStringResource((Class<?>) null, key, locale, style, variation);
    }
}

class BundleClassloader extends ClassLoader {

    private Map<String, URL> resources;
    private int prefixLength;

    public BundleClassloader(String prefix, List<URL> urls) {

        resources = new HashMap<String, URL>();
        prefixLength = prefix.length();
        for (URL url : urls) {
            String path = url.getPath();
            resources.put(path.substring(path.lastIndexOf('/') + 1), url);
        }
    }

    @Override
    protected URL findResource(String name) {
        if (name.length() < prefixLength)
            return null;
        return resources.get(name.substring(prefixLength));
    }

}