2011-01-14 3 views
3

J'ai une bibliothèque foo.jar qui contient un fichier svnversion.properties (regarde comme svnversion=12345M ou autre) et la méthode statique suivante dans un class SVNVersion:java: obtenir la bonne ressource

public static SVNVersion fromString(String s) { ... } 
public static SVNVersion fromResources(Class<?> cl) { 
    ResourceBundle svnversionResource = ResourceBundle.getBundle(
     "svnversion", Locale.getDefault(), cl.getClassLoader()); 
    if (svnversionResource.containsKey("svnversion")) 
    { 
     String svnv = svnversionResource.getString("svnversion"); 
     return fromString(svnv); 
    } 
    else 
    { 
     return null; 
    } 
} 

J'ai aussi une bibliothèque bar.jar que contient également un fichier svnversion.properties (disons qu'il contient svnversion=789).

Cependant, quand je lance ce qui suit dans un class SomeClassInBarJar qui est dans bar.jar:

SVNVersion vfoo = SVNVersion.fromResources(SVNVersion.class); 
SVNVersion vbar = SVNVersion.fromResources(SomeClassInBarJar.class); 

et imprimer le résultat, je vois 789 deux fois. De toute évidence, je ne le fais pas correctement. Comment puis-je obtenir le bon fichier svnversion.properties dans la racine du fichier jar contenant une classe donnée? (En supposant qu'il est là)


edit: Je viens d'essayer

InputStream is = cl.getResourceAsStream("/svnversion.properties"); 

et il a le même problème. Il semble que je ne puisse accéder qu'au fichier /svnversion.properties du fichier jar principal et non au /svnversion.properties de la bibliothèque.

+1

Donner un nom de classe différent ne signifie pas nécessairement des chargeurs de classe différents. Je ne pense pas que ce soit possible de faire comme ça –

+0

@Teja: Je l'ai compris. :-) Je suis intéressé par la façon de le faire correctement. –

+0

Pouvez-vous expliquer comment faire celui-ci? –

Répondre

2

Vous ne pouvez évidemment pas utiliser cette approche, car le fichier svnversion.properties est toujours utilisé pour le chargeur de classe. C'est le même comportement que vous verriez pour les classes: si deux classes avec le même nom sont sur le classpath, c'est tout ce qui vient en premier qui est utilisé.

Une approche (alambiquée) serait de savoir ce jar une classe appartient, puis récupérer svnversion.properties dans ce pot:

public static JarFile getJarFile(Class<?> cl) { 
    URL classUrl = cl.getResource(cl.getSimpleName() + ".class"); 
    if (classUrl != null) { 
     try { 
      URLConnection conn = classUrl.openConnection(); 
      if (conn instanceof JarURLConnection) { 
       JarURLConnection connection = (JarURLConnection) conn; 
       return connection.getJarFile(); 
      } 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 
    } 
    return null; 
} 

public static SVNVersion fromResources(Class<?> cl) { 
    JarFile jarFile = getJarFile(cl); 
    ZipEntry entry = jarFile.getEntry("svnversion.properties"); 
    Properties props = new Properties(); 
    try { 
     props.load(jarFile.getInputStream(entry)); 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } 

    if (props.containsKey("svnversion")) { 
     String svnv = props.getProperty("svnversion"); 
     return fromString(svnv); 
    } else { 
     return null; 
    } 
} 

Voilà pourquoi, à mon humble avis, vous seriez probablement mieux stocker les svn numéro de version dans la classe eux-mêmes en tant que variables statiques finales (et en utilisant svn $Revision$ mot-clé).

+0

svn mot-clé de substitution $ Revision $ s'applique uniquement aux fichiers individuels; Je veux le résultat de l'exécution svnversion.exe sur mon contrôle entier. Quoi qu'il en soit, la question ne concerne pas seulement les versions de svn, mais aussi l'obtention de ressources à partir des fichiers de bibliothèque par rapport aux fichiers d'application. Merci pour les autres suggestions. –

+1

Je l'ai compris, mais il est clair que vous ne comprenez pas le fonctionnement de la gestion de classe. À moins de charger les différents jars dans différents chargeurs de classe, vous ne réussirez jamais à obtenir ce que vous voulez. –

+0

"mais il est clair que vous ne comprenez pas la façon dont fonctionne le chargement de classes." - Je ne suis pas du tout en train de mal comprendre la classification. Ce que j'ai mal compris, c'est la façon dont getResource() et getResourceStream() et getResourceBundle() ont fonctionné en conjonction avec classloaders. –