简体   繁体   中英

How can I find out where a ResourceBundle came from?

Given a ResourceBundle object, is there a way to get a URL or other indicator as to where it was found when it was looked up?

The ResourceBundle is being created with:

ResourceBundle rb = ResourceBundle.getBundle("filename");

And it is being loaded from a file subdir/filename.properties, in most cases. I'd like to be able to programmatically refer to this location, rather than hardcoding it.

Judging from the documentation , you can't, because it's a class that can be subclassed in arbitrary ways (not necessarily associated with a URL or classname) and there's no linkage back to the creator.

Also note the constructor for PropertyResourceBundle : it takes an InputStream which can be obtained anywhere: you can provide your own InputStream by subclassing it, to provide arbitrary data that is generated out of thin air.

Try this:

URL location = getClass().getClassLoader().getResource("filename.properties");

That's the mechanism used by ResourceBundle to find the resource. Check out the [Javadoc for ResourceBundle ][1] to see the specifics of how it maps a bundle name to an underlying resource. You may need to be a bit more clever if you have locales and things involved.

[1]: http://java.sun.com/javase/6/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String , java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control)

If you are able to modify all invokations of ResourceBundle.getResource, you can pass your own implementation of ResourceBundle.Control to cache the URL, from which the resolved bundle is actually loaded

public class ResourceBundleSourceControl extends ResourceBundle.Control {

private static final Map<ResourceBundle, URL> sources = 
    new HashMap<ResourceBundle, URL>();     

private String bundleName;

@Override
public ResourceBundle newBundle(String baseName, Locale locale, String format,
        ClassLoader loader, boolean reload) throws IllegalAccessException,
        InstantiationException, IOException {
    ResourceBundle rb =  super.newBundle(baseName, locale, format, loader, reload);
    URL sourceURL = loader.getResource(toResourceName(bundleName, "properties"));
    if(rb != null && sourceURL != null) {
        synchronized(sources) {
            sources.put(rb, sourceURL);
        }
    }
    return rb;
}

@Override
public String toBundleName(String arg0, Locale arg1) {
    bundleName = super.toBundleName(arg0, arg1);
    return bundleName;
}

public static URL getSourceURL(ResourceBundle b) {
    synchronized (sources) {
        return sources.get(b);              
    }
}

The drawback is, that you have to pass an instance of this class to each invocation of ResourceBundle.getBundle. Since the resource bundles are lazily cached, you can not be sure that each retrieval of the bundle will actually load it, which is necessary for the Control implementation to catch it.

After loading the bundle, you can use the static getSourceURL method, to find the URL from which it was actually loaded:

ResourceBundle rb = ResourceBundle.getBundle(
    "props.Default", new ResourceBundleSourceControl()); 
System.out.println(
    "URL: " + ResourceBundleSourceControl.getSourceURL(rb));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM