2009-09-30 5 views
2

Учитывая объект ResourceBundle, есть ли способ получить URL-адрес или другой показатель того, где он был найден, когда он был просмотрен?Как узнать, откуда появился ResourceBundle?

ResourceBundle создается с:

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

И загружается из файла подкаталог/filename.properties, в большинстве случаев. Я хотел бы иметь возможность программно ссылаться на это местоположение, а не на жесткое кодирование.

ответ

2

Попробуйте это:

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

Это механизм, используемый ResourceBundle, чтобы найти ресурс. Проверьте [Javadoc для ResourceBundle] [1], чтобы узнать, как он сопоставляет имя пакета с базовым ресурсом. Возможно, вам нужно быть немного умнее, если у вас есть локальные и другие предметы.

[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)

+2

, что, как вы получите ResourceBundle данного класса. OP спрашивает, как получить файл/класс/URL, заданный ResourceBundle, который плавает вверх по течению, а не по течению. –

+0

Спасибо! Это в значительной степени то, что я сделал. Затем, поскольку я контролировал, как я получал ResourceBundle, я вернулся и разложил его и просто загрузил объект Properties из этого URL-адреса, повторно используя URL-адрес позже, когда мне нужно было перейти к файлу: новый файл (location.toURI()) – skiphoppy

2

Судя по documentation, вы не можете, потому что это класс, который может быть подклассифицирован произвольными способами (не обязательно связан с URL-адресом или именем класса), и нет никакой связи с создателем.

Также обратите внимание на конструктор для PropertyResourceBundle: он принимает InputStream, который можно получить в любом месте: вы можете предоставить свой собственный InputStream путем подклассификации его, чтобы обеспечить произвольные данные, которые генерируются из воздуха.

2

Если вы можете изменить все invokations из ResourceBundle.getResource, вы можете пройти самостоятельно реализация ResourceBundle.Control кэшировать URL, с которого фактически загружена разрешенная пучок

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);    
    } 
} 

недостаток заключается в том, что вы должны передать экземпляр этого класса для каждого вызова ResourceBundle.getBundle. Так как пакеты ресурсов лениво кэшированы, вы не можете быть уверены, что каждое извлечение пакета действительно загрузит его, что необходимо для реализации Control, чтобы его поймать.

После загрузки пакета, вы можете использовать статический метод getSourceURL, чтобы найти URL, из которого он был на самом деле загружен:

ResourceBundle rb = ResourceBundle.getBundle(
    "props.Default", new ResourceBundleSourceControl()); 
System.out.println(
    "URL: " + ResourceBundleSourceControl.getSourceURL(rb)); 
Смежные вопросы