How to check if a Java ResourceBundle is loadable, without loading it? - java

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)) != null) {
return true;
}
// }
}
return false;
}
}

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.

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.

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

Related

Recorder does not fire in native executable

In our setup, we perform some STATIC-INIT build steps including adding all resource paths to a list in an object. We use a Recorder for this, because the object cannot be accessed during the static init phase. In JVM mode, we see that the list does indeed contain all resource paths. However, this is not the case in Native mode. The list remains empty, even though the build logs show that we iterated over the resources and added them to the list.
This is what our setup looks like:
First: The file that is accessible at runtime and contains all resource paths.
#ApplicationScoped
public class ServiceResourcesList {
private List<String> resources;
public ServiceResourcesList() {
resources = new ArrayList<>();
}
public void addResource(String resource) {
this.resources.add(resource);
}
public List<String> getResources() {
return resources;
}
public List<String> getResources(Predicate<String> filter) {
return resources.stream().filter(filter).collect(Collectors.toList());
}
}
The recorder, which returns a BeanContainerListener:
#Recorder
public class ServiceResourcesListRecorder {
public BeanContainerListener addResourceToList(String resource) {
return beanContainer -> {
ServiceResourcesList producer = beanContainer.instance(ServiceResourcesList.class);
producer.addResource(resource);
};
}
}
And finally the (simplified) buildstep. Note that we use a BuildProducer which should make sure that the objects have been registered already before applying the Recorder methods.
#BuildStep
#Record(STATIC_INIT)
void createResourceList(final BuildProducer<BeanContainerListenerBuildItem> containerListenerProducer, ServiceResourcesListRecorder recorder) {
// Some code to get the resource paths, but this could be anything
// ...
for (String resourcePath: resourcePaths) {
LOGGER.info(resourcePath + " added to recorder");
containerListenerProducer.produce(new BeanContainerListenerBuildItem(recorder.addResourceToList(resourcePath)));
}
}
Am I doing something wrong? Are recorders not meant to be used for native executables? Should I add RegisterForReflection somewhere?
Thanks
We solved this problem by using RUNTIME-INIT and static methods instead.

Try with Resource Java 7

I have a simple java program to test Try with resource in java , I am getting the File Not Found error, The Program and file are in the same package, Can somebody tell me what directory does File with resource start to search with
public class LoadConfigFile {
public static String getProperty(String propertyName) {
String propertyValue = null;
try (InputStream in = new FileInputStream("Properties.properties")) {
Properties prop = new Properties();
prop.load(in);
propertyValue = prop.getProperty(propertyName);
} catch (IOException e) {
System.out.println("Error Reading Property File" + e.getMessage().toString());
}
return propertyValue;
}
}
Properties.properties
properties.one=1
properties.two=2
properties.three=3
properties.four=4
properties.five=5
Main.java
public class Main {
public static void main(String[] args) {
String s = LoadConfigFile.getProperty("property.one");
System.out.println(s);
}
}
Working directory for process, to get that in Java you can use
System.out.println(System.getProperty("user.dir"));
If you have file within a Java package you should not access it as file but as resource:
InputStream in = this.getClass().getResourceAsStream("Properties.properties");
If you look at the source code for the FileInputStream constructor, you'll see that it, in turn, invokes File's constructor.
And if you have a look at the documentation for File, you will find a good explanation of how the path string is interpreted.
In particular, notice the following snippet:
A pathname, whether abstract or in string form, may be either absolute
or relative. An absolute pathname is complete in that no other
information is required in order to locate the file that it denotes. A
relative pathname, in contrast, must be interpreted in terms of
information taken from some other pathname. By default the classes in
the java.io package always resolve relative pathnames against the
current user directory. This directory is named by the system property
user.dir, and is typically the directory in which the Java virtual
machine was invoked.

Eclipse tracing.What is best practice?How to get instance of DebugTrace?

I'm working on RCP aplicattion, that works on Eclipse 4 platform(Luna). I neeed to find out how to get instance that implement tracing inside my Application. I found out the following ways
-
Using ILog interface, that can be get via Platform.getLog call. ILog has good point. It prints to .log file that located in .metadata, but
it get IStatus object as parameter. So for logging each line to log I have to created new instance of Status object. And it cannot put automatically information about caller like class name etc.(like Log4j, LogBack)
I found interface DebugTrace that provide good functionality for traicing. It can be obtained via DebugOptions inerface(DebugOptions.newDebugTrace()). To my regret I could not find appropriated way for getting instance of DebugOptions
To use DebugTrace, add this to the plugin Activator:
private DebugTrace tracer = null;
public static DebugTrace getTrace()
{
return plugin.tracer;
}
public void start(final BundleContext context) throws Exception
{
...
final Hashtable<String, String> properties = new Hashtable<String, String>(4);
properties.put(DebugOptions.LISTENER_SYMBOLICNAME, "org.eclipse.ui.trace"); //$NON-NLS-1$
context.registerService(
DebugOptionsListener.class.getName(),
new DebugOptionsListener()
{
#Override
public void optionsChanged(DebugOptions options)
{
tracer = options.newDebugTrace(context.getBundle().getSymbolicName());
}
}, properties);
You will need to add a .options file to the plugin project which will contain your logging options:
# Editor-related tracing
com.acme.atf.app/trace/editor=false
#Start-up tracing
com.acme.atf.app/trace/startup=true
org.eclipse.core.jobs/jobs=true
org.eclipse.core.jobs/jobs/beginend=true
org.eclipse.core.jobs/jobs/errorondeadlock=true
Hope this helps...

Load multiple locale specific properties files in internationalization with resource bundle in java

I have four properties files
Application.properties
Application_fr_FR.properties
Database.properties
Database_fr_FR.properties
So now I need internationalization in multiple programs, so now I need to load multiple properties files and get the key-value pair of values from properties files specific to a locale. For that I have a ResourceBundleService.java
public class ResourceBundleService {
private static String language;
private static String country;
private static Locale currentLocale;
static ResourceBundle labels;
static {
labels = ResourceBundle
.getBundle("uday.properties.Application");
labels = append(Database.properties");
//** how to append existing resource bundle with new properties file?
}
public static String getLabel(String resourceIndex, Locale locale) {
return labels.getString(resourceIndex);
//How to get locale specific messages??
}
}
Hope the question is clear.
You need to call ResourceBundle.getBundle(baseName, locale) each time in getLabel. ResourceBundle maintains an internal cache so it wont load all props files each time:
public static String getLabel(String resourceIndex, Locale locale) {
ResourceBundle b1 = ResourceBundle.getBundle("uday.properties.Application", locale);
if (b1.contains(resourceIndex)) {
return b1.getString(resourceIndex);
}
ResourceBundle b2 = ResourceBundle.getBundle("uday.properties.Database", locale);
return b2.getString(resourceIndex);
}
For the time being use Application_fr.properties; les Canadiens will be thankful. With Locale.setDefault(availableLocale) elect an available locale. The root locale properties, Application.properties, should also contain the language keys. You could copy the French ones. In that case you need not set the default locale.
Lets check this implementation on github it works really nice. It requires the following function naming convention:
MultiplePropertiesResourceBundle is an abstract base implementation to allow to combine a ResourceBundle from multiple properties files whereas these properties files must end with the same name - the base-name for these combined ResourceBundle.
If you'll use it at the first you need to implement abstract class MultiplePropertiesResourceBundle as below:
import ch.dueni.util.MultiplePropertiesResourceBundle;
public class CombinedResources extends MultiplePropertiesResourceBundle {
public CombinedResources() {
super("package_with_bundles");
}
}
then you should implement empty class which extends out CombinedResources:
public class CombinedResources_en extends CombinedResources {}
and so on for other languages. After that you can use your bundle as below:
ResourceBundle bundle = ResourceBundle.getBundle("CombinedResources");
This bundle will be use all properties files inside package_with_bundles. For more information just look inside github repo.

How can i specify a different attachments path under play framework

I'm using play framework now, i already know we can specify the attachments path in application.conf:
# Store path for Blob content
attachments.path=data/attachments
My application have different kinds of pictures, i need to separate those pictures into different directories.
How can i implement my thought ?
Many thanks!
This is my controller code:
public static void uploadAvatar(Blob file){
if(request.isNew){
Long userId = Long.parseLong(session.get(Constants.USER_ID_IN_SESSION));
User user = User.findById(userId);
// Delete old picture
if (user.avatar.getFile() != null) {
user.avatar.getFile().delete();
}
user.avatar = file;
user.avatarFileName = file.getFile().getName();
user.save();
}
Users.settings();
}
I would make a class which extends the current blob.class (http://www.playframework.org/documentation/api/1.2.4/play/db/jpa/Blob.html), and reimplement the getStore() method to read a different property than attachments.path (ie avatar.path).
Good luck!

Categories