package calculette;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class CalculettePlugins extends Calculette {

	private static final Operateur[] OPERATEURS_VIDES = new Operateur[0];
	private static final ChargeurOperateur CHARGEUR = new ChargeurOperateur();
	
	public CalculettePlugins(String repertoireOperateurs) {
		super(OPERATEURS_VIDES);
		try {
			CHARGEUR.chargerOperateurs(this, repertoireOperateurs);
		} catch (Exception e) {
			throw new Error("Chargement opérateurs impossibles, "
					+ e.getMessage());
		}
	}

	static class ChargeurOperateur extends ClassLoader {

		void chargerOperateurs(Calculette calculette, String repertoire)
				throws ClassNotFoundException, InstantiationException,
				IllegalAccessException {
			String[] fichiers = new File(repertoire).list();
			String suffixe = ".class";
			if (fichiers != null) {
				for (String f : fichiers) {
					if (f.endsWith(suffixe)) {
						String prefixe = f.substring(0, f.length()
								- suffixe.length());
						Class<? extends Operateur> c = findClass(repertoire,
								prefixe);
						calculette.ajouter(c.newInstance());
					}
				}
			}
		}

		protected Class<? extends Operateur> findClass(String rep, String nom)
				throws ClassNotFoundException {

			File f = new File(rep + File.separator + nom + ".class");
			long size = f.length();
			if (size > Integer.MAX_VALUE) {
				throw new ClassFormatError("Fichier " + nom + " trop long");
			}
			byte[] buffer = new byte[(int) size];

			try {
				RandomAccessFile randomAccessFile = new RandomAccessFile(f, "r");
				randomAccessFile.readFully(buffer, 0, buffer.length);
				randomAccessFile.close();
			} catch (IOException e) {
				throw new ClassNotFoundException(e.toString());
			}
			Class<?> c = defineClass(nom, buffer, 0, buffer.length);
			return c.asSubclass(Operateur.class);
		}
	}
}
