Cargar recurso desde cualquier lugar en classpath

Tengo una aplicación Java simple que carga un archivo de propiedades del paquete actual.

this.getClass().getResourceAsStream("props.properties"); 

Esto funciona bien cuando el archivo de propiedad que quiero está en el paquete actual. Sin embargo, quiero empaquetar esta aplicación como un JAR y definir y anular con un nuevo archivo de propiedades donde lo uso. ¿Hay alguna forma de cargar el primer recurso llamado “props.properties” que está en el classpath?

Quiero que sea tan fácil sobrescribir el archivo de propiedades a través de la línea de comando:

 java.exe -classpath props.properties;myJar.jar com.test.MyApp 

No quiero tener que desempaquetar el JAR y modificar el archivo de propiedades para cambiar algo. Siento que me falta algo obvio …

Si todo lo demás falla, podría usar dos nombres de archivo diferentes, por ejemplo props-default.properties dentro de myJar.jar y props.properties para anular en la línea de comandos. En tu código, intentas cargar props.properties archivo props.properties y props-default.properties a props-default.properties si no se encuentra.

El javadoc para Class.getResourceAsStream() documenta la lógica de búsqueda:

Si el nombre comienza con un '/' ( '\u002f' ), el nombre absoluto del recurso es la parte del nombre que sigue a ‘/’.

De lo contrario, el nombre absoluto es de la siguiente forma:
modified_package_name/name

Donde el modified_package_name es el nombre del paquete de este objeto con ‘/’ sustituido por '.' ( '\u002e' ).

En otras palabras, el nombre del recurso pasado al método debería parecerse a /com/package/p2/props.properties si el props.properties se almacena en el paquete com.package.p2 lugar de la clase actual.

Estoy seguro de que es demasiado tarde para la respuesta, pero podría ser interesante para los usuarios de Google ayudar a este pequeño fragmento de código a cargar un archivo de propiedades desde cualquier lugar en el Classpath.

 ClassLoader cl = ClassLoader.getSystemClassLoader(); if (cl != null) { URL url = cl.getResource(CONF_PROPERTIES); if (url == null) { url = cl.getResource("/" + CONF_PROPERTIES); } if (url != null) { try { InputStream in = url.openStream(); props = new Properties(); props.load(in); } catch (IOException e) { // Log the exception } finally { // close opened resources } } } 

No estoy seguro, pero tal vez: ClassLoader.getResourceAsStream()

EDITAR:

No creo que esto sea significativamente diferente de this.getClass().getResourceAsStream() de la pregunta, ya que como se mencionó, aún debe obtener el ClassLoader que desea usar para cargar el recurso.

Dado que usted proporciona el recurso en -classpath en su ejemplo, debería estar disponible desde el mismo cargador de clase que su clase “principal” (en la JVM de SUN, eso es sun.misc.Launcher$AppClassLoader , no estoy seguro si esto puede / hace variar para otras implementaciones de JVM).