VersionClassLoader.java

import java.io.*;
import java.util.*;
import java.security.*;
public class VersionClassLoader extends SecureClassLoader {
  // Version des classes chargées
  private String version;

  public VersionClassLoader(String version) {
    this.version = version;
  }
  public VersionClassLoader(ClassLoader parent, String version) {
    super(parent);
    this.version = version;
  }
  /** Méthode de chargement de classe respectant la hiérarchie
      des chargeurs de classes. Cette méthode redéfinit la méthode
      findClass de SecureClassLoader. */
  protected Class findClass(String initialName)
    throws ClassNotFoundException {
    // Récupère le nom de la classe incluant la version
    String name = getVersionName(initialName);
    // Récupération du classpath
    StringTokenizer st = getClasspath();
    // Recherche du fichier dans les répertoires du classpath
    while (st.hasMoreTokens()) {
      try {
    File dir = new File(st.nextToken());
    File f = new File(dir,name);
    // Récupération du bytecode de la classe dans result
    byte[] result = loadClassData(f);
    // Objet spécifiant les droits de la classe 
    CodeSource codeSource = new CodeSource(dir.toURL(),null);
    // Création de l'objet classe correspondant
    Class c = defineClass(initialName, result, 0,
                  (int)f.length(), codeSource);
    // Édition de liens de la classe construite
    resolveClass(c);
    return c;
      } catch (IOException e) {
    continue;
      }
    }
    throw new ClassNotFoundException(initialName);
  }

  
  /** Retourne un tokenizer du classpath. */
  private StringTokenizer getClasspath() {
    String classpath = System.getProperty("java.class.path");
    if (classpath == null) classpath = ".";
    return new StringTokenizer(classpath,":");
  }
  /** Contruit un tableau d'octets contenant le contenu du fichier f. */
  private byte[] loadClassData(File f) throws IOException {
    DataInputStream input =
      new DataInputStream(new FileInputStream(f));
    byte[] content = new byte[(int)f.length()];
    input.readFully(content);
    return content;
  }
  /** Construit le nom du fichier à rechercher dans le
      classpath. Les '.' sont remplacés par le séparateur
      de fichiers et la version du package ajoutée entre le
      nom du fichier .class et le nom du répertoire. */
  private String getVersionName(String initialName) {
    int index = initialName.lastIndexOf('.');
    if (index == -1) 
      return  version + File.separator + initialName + ".class";
    String name = initialName.replace('.',File.separatorChar);
    return (name.substring(0,index) + File.separator + version +
        File.separator + name.substring(index) + ".class");
  } 
}