2

I have a Java application with multiple modules, each module has a jar file. each jar file follows same folder structure called META-INF/propsIs there a way in java to load all the property files which are in `META-INF/props of multiple jars using a wild card?

Something like

ClassLoader.getSystemResourceAsStream("META-INF/props/*.properties");

I know that this method does not accept wild cards and does not return array of streams , but is it possible to do something like this?

Puru--
  • 1,111
  • 12
  • 27
  • Not really. You can use [`ClassLoader#findResources`](http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#findResources(java.lang.String)), which will return an `Enumeration` of all resources named the same within the class path, but this still expects a fully qualified path and name – MadProgrammer Sep 26 '14 at 01:38

2 Answers2

2

No, there is no standard/reliable way to do this. Some libraries take advantage of common patterns of ClassLoader.getResources implementations (specifically, that they usually always return "file:" or "jar:file:" URLs) in order to support wildcards in resource lookups. For example, the Wildcards in application context constructor resource paths explains how Spring does this, and it lists several caveats ("Implications on portability", "Classpath*: portability", "notes relating to wildcards").

Brett Kail
  • 33,593
  • 2
  • 85
  • 90
  • Yeah I know that spring supports wild card loading, that is the reason I asked the question, I thought Java has in built mechanism to scan classpath. – Puru-- Sep 29 '14 at 23:06
  • The answer is that it does not. If you're willing to make assumptions about the environment, you can emulate. – Brett Kail Sep 30 '14 at 04:52
  • @Puru I filed an issue with Spring to separate out their resource loading into a lightweight artifact: https://jira.spring.io/browse/SPR-12508 Please vote it up if you like. – Adam Gent Dec 04 '14 at 19:29
0

I wrote some code to get around this this limitation.

I read all entries from class path and determine if it is a folder or a JAR file and then look for the entries in "META_INF/props". If the entry is a property, I load it.

Below is the code, it is not refined but it gives general idea.

try{
    URL[] urls = ((URLClassLoader) LoaderTest.class.getClassLoader()).getURLs();
    HashMap<String, Properties> mapProperties = new HashMap<String, Properties>();

    for(URL url: urls){
        File file = new File(url.getFile());
        if(file.isDirectory()){
            System.out.println("Directory: " +file.getName());
            File propFolder = new File(file.getAbsolutePath() + "/META-INF/props");
            if (propFolder.exists() && propFolder.isDirectory()){
                for(File f: propFolder.listFiles()){
                    if(f.getName().endsWith("properties") || f.getName().endsWith("props")){
                        Properties props = new Properties();
                        props.load(new FileReader(f));
                        String appName = props.getProperty("load.global.props.appName");
                        if(appName != null){
                            if( mapProperties.get(appName) == null) {
                                mapProperties.put(appName, props);
                            } else {
                                mapProperties.get(appName).putAll(props);
                            }
                        }
                    }
                }
            }
        } else if (file.getName().endsWith("jar")){
            System.out.println("Jar File: " + file.getName());
            JarFile jarFile = null; 
            try{
                jarFile = new JarFile(file);
                Enumeration<JarEntry> entries = jarFile.entries();
                while ( entries.hasMoreElements() ){
                    JarEntry entry = entries.nextElement();
                    if ( entry.getName().startsWith("META-INF/props") && 
                            (entry.getName().endsWith("properties") ||
                            entry.getName().endsWith("props"))){
                        System.out.println("Prop File: " + entry.getName());
                        Properties props = new Properties();
                        props.load(jarFile.getInputStream(entry));
                        String appName = props.getProperty("load.global.props.appName");
                        if(appName != null){
                            if( mapProperties.get(appName) == null) {
                                mapProperties.put(appName, props);
                            } else {
                                mapProperties.get(appName).putAll(props);
                            }

                        }
                    }
                }
            } finally {
                if ( jarFile != null ) jarFile.close();
            }
        }
    }

} catch(Exception e){
    e.printStackTrace();
}
Puru--
  • 1,111
  • 12
  • 27