views:

580

answers:

3

I would like to check the existence of a ResourceBundle without actually loading it.

Typically, I'm using Guice, and at initialization time, I want to check the existence, while at execution time, I want to load it. If the bundle doesn't exist, I want an early report of the inexistence of the RB.

If it was possible to get the ResourceBundle.Control instance used for a specific ResourceBundle, I would have no problem getting the basic information to build the actual resource name (using toBundleName() and toResourceName()), but it is not the case at that level.

Edit:

Ok, I found the way to do it. I'll create a ResourceBundle.Control that is extensible (using a custome addFormat(String, Class)) to store all the bundle formats, then use another method of my own to check all possible file names for a specific locale (using Class.getResource as indicated here below).

Coding speaking:

class MyControl extends ResourceBundle.Control {
  private Map<String,Class<? extends ResourceBundle>> formats = new LinkedHashMap();
  public void addFormat(String format,Class<? extends ResourceBundle> rbType) {
    formats.put(format, rbType);
  }
  public boolean resourceBundleExists(ClassLoader loader, String baseName, Locale locale) {
    for (String format: formats.keySet()) {
      // for (loop on locale hierarchy) {
        if (loader.getResource(toResourceName(toBundleName(baseName, locale), format))) {
          return true;
        }
      // }
    }
    return false;
  }
}
A: 

You can load the bundles, thus making your checks, and then call ResourceBundle.clearCache() so that they are loaded again next time.

This happens once (at initialization time), and it isn't such a heavy operation, so it won't be a problem.

Or you can simply try to find whether a resource is present on the classpath. For example the fallback .properties file, or the properties file for your default locale.

Finally, after having a look at the code for ResourceBundle.Control, you have the option to do what they do in the newBundle() method.

Bozho
I certainly don't want to load twice the bundle. I would like to perform the check for early failure, so not spend the loading time in the initialization time.
Frór
why do you worry so much about that loading time? it happens once, and, well, loading a bundle isn't the most expensive operation.
Bozho
Ok, in fact, there is the preinitialization time, the initialization time and the run time. I develop an API over Guice that needs to fast fail and any IO is time-consuming so that would become "not-so-fast fail". Performing one IO check is acceptable like in the other answer, but not one full load, with the properties loading/parsing, etc.Short answer: it's part of my prerequisites.
Frór
that's still strange for me. applications are even not supposed to be started that often.
Bozho
I understand your concern. I had the same when I planned the project, but the extensibility of the project explains the request.By the way, it is not a J2EE application: only J2SE one.
Frór
anyway, check my update for looking at the source of the newBundle method
Bozho
+1  A: 

If the default bundle must exists you can do:

Class.getResource("/my/path/to/bundle.properties")

and it will return an URL to the file or null if it doesn't exists.

Of course use the correct class or classloader if you have many.

EDIT: if you have resources as classes you have to check also

Class.getResource("/my/path/to/bundle.class")

In Java 6 you can store resource bundles in XML. I don't know how ResourceBundle class lookups this resource, but I bet it's in the same way.

helios
Rule: bundle "a.b.c" is resource "/a/b/c.properties" (default file)
helios
The problem of this one is that I suppose that I have only properties files. I might as well have XML-based properties or classes.
Frór
I give a plus for the Class.getResource(), but with my previous comment I don't get the full answer to my question.
Frór
Understood. I didn't know bundles in XML or classes :)
helios
A: 

Something like this, maybe

ResourceBundle bundle;
public PropertiesExist() {
    String propsFile = "log4j";
    String propsPath = this.getClass().getClassLoader().getResource(".").getPath();
    File f = new File(propsPath, propsFile + ".properties");
    if(!f.exists()){
        System.out.println("File not found!!!!");
        System.exit(-1);
    }
    bundle = ResourceBundle.getBundle(propsFile);
    System.out.println(bundle.getString("log4j.rootLogger"));
}

public static void main(String[] args) {
     new PropertiesExist();         
}

This will look for the logging file, log4.properties, if not found program will exit

Kennet