Java tutorial
/* * Copyright (C) 2006-2010 Thomas Chemineau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.aepik.alasca.core.ldap; import net.aepik.alasca.core.History; import net.aepik.alasca.core.ldap.value.Oid; import org.apache.commons.lang3.ArrayUtils; import java.io.File; import java.lang.reflect.Field; import java.net.URL; import java.net.URLDecoder; import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Observable; import java.util.Properties; import java.util.Set; import java.util.Vector; import java.util.jar.*; /** * Cet objet est un schma LDAP au sens large. Il doit contenir des dfinitions * de type objectClass ou AttributeType, par l'intermdiaire de l'objet Java * SchemaObject. */ public class Schema extends Observable { /** * L'ensemble des objets du schema */ private Hashtable<String, SchemaObject> objets; /** * Schema properties */ private Properties proprietes; /** * La syntaxe du schema */ private SchemaSyntax syntax; /** * Indique si la syntaxe a change */ private boolean isSyntaxChanged; /** * Schema name. * @var String */ private String name; /** * L'historique d'ordre des objets */ private History objectsOrder; /** * A random object identifier prefix */ private String objectIdentifierPrefix; /** * A random object identifier suffix */ private String objectIdentifierSuffix; /** * Construit un schema vide. * @param name Schema name * @param s Schema syntax */ public Schema(String name, SchemaSyntax s) { this.name = name; objets = new Hashtable<String, SchemaObject>(); proprietes = new Properties(); syntax = s; isSyntaxChanged = false; objectsOrder = new History(); objectIdentifierPrefix = null; objectIdentifierSuffix = null; } /** * Construit un schema en le remplissant * d'objets SchemaObject. * @param name Schema name * @param s Schema syntax * @param objs Des objets du schema. */ public Schema(String name, SchemaSyntax s, Vector<SchemaObject> objs) { this.name = name; objets = new Hashtable<String, SchemaObject>(); proprietes = new Properties(); syntax = s; isSyntaxChanged = false; addObjects(objs); objectIdentifierPrefix = null; objectIdentifierSuffix = null; } /** * Ajoute un objet au schema. * @param o Un objet du schema. * @return True si l'objet n'existe pas dj, false sinon. */ public boolean addObject(SchemaObject o) { try { if (o == null || o.getId() == null) { return false; } if (!contains(o.getId())) { objets.put(o.getId(), o); objectsOrder.insertElementInLastPosition(o); notifyUpdates(); return true; } } catch (Exception e) { e.printStackTrace(); } return false; } /** * Ajoute un objet au schema mme s'il existe. * @param o Un objet du schema. * @return True si l'ajout s'est bien pass, false sinon. */ public boolean addOrReplaceObject(SchemaObject o) { try { if (o == null || o.getId() == null) { return false; } objets.put(o.getId(), o); notifyUpdates(); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * Ajoute un ensemble d'objets au schema. * @param v Un ensemble d'objets du schema. * @return True si l'opration a russi, false sinon. * Si l'opration n'a pas russi, aucun objet n'aura t ajout. */ public boolean addObjects(SchemaObject[] v) { boolean ok = true; for (int i = 0; i < v.length && ok; i++) { ok = addObject(v[i]); } if (ok) { notifyUpdates(); return true; } // // Si l'opration n'a pas russi, c'est dire qu'un objet, figurant // dans l'ensemble des objets que l'on tente d'insrer, possde un id // qui existe dj dans le schema courant, alors on effectue // l'opration inverse: on supprime tout objet insr durant // l'opration prcdente. // for (SchemaObject o : v) { delObject(o.getId()); } return false; } /** * Ajoute un ensemble d'objets au schema. * @param v Un ensemble d'objets du schema. * @return True si l'opration a russi, false sinon. * Si l'opration n'a pas russi, aucun objet n'aura t ajout. */ public boolean addObjects(Vector<SchemaObject> v) { SchemaObject[] o = new SchemaObject[v.size()]; Iterator<SchemaObject> it = v.iterator(); int position = 0; while (it.hasNext()) { o[position] = it.next(); position++; } return addObjects(o); } /** * Indique si l'objet identifi par id existe dans le schema. * @param id Une chaine de caractres reprsentant l'id d'un objet du schma. * @return True si l'objet d'identifiant id existe dans le schema, false sinon. */ public boolean contains(String id) { try { if (id == null || objets == null) { return false; } if (objets.containsKey(id)) { return true; } } catch (Exception e) { e.printStackTrace(); } return false; } /** * Retourne le nombre d'objets que contient le schma. * @return int Le nombre d'objets du schma. */ public int countObjects() { return objets.size(); } /** * Crer un schma et charge les objets lu partir d'un fichier dans ce * nouveau schma. * @param SchemaSyntax syntax * @param String filename * @param boolean load * @return SchemaFile Un objet SchemaFile contenant les objets. */ public static SchemaFile createAndLoad(SchemaSyntax syntax, String filename, boolean load) { SchemaFileReader sReader = syntax.createSchemaReader(); SchemaFile sFile = new SchemaFile(filename, sReader, null); if (load) { sFile.read(); } return sFile; } /** * Supprime un objet du schema. * @param id Une chaine de caractres reprsentant l'id d'un objet du schema. * @return True si l'objet d'identifiant id existe dans le schema, false sinon. */ public boolean delObject(String id) { if (contains(id)) { SchemaObject o = objets.remove(id); objectsOrder.removeElement(o); notifyUpdates(); return true; } return false; } /** * Generate a random object identifier. * @return String A random object identifier string. */ public String generateRandomObjectIdentifier() { if (this.objectIdentifierPrefix == null) { objectIdentifierPrefix = new String("0.1.2.3.4.5.6"); } if (this.objectIdentifierSuffix == null) { objectIdentifierSuffix = new String("0"); } int suffix = (new Integer(objectIdentifierSuffix)).intValue(); objectIdentifierSuffix = String.valueOf(++suffix); String roid = new String(objectIdentifierPrefix + "." + objectIdentifierSuffix); return roid; } /** * Retourne l'historique d'ajout du schma. * @return History Un historique en fonction des donnes actuelles du schma. */ public History getHistory() { return objectsOrder; } /** * Get the name of this schema. * @return String */ public String getName() { return this.name; } /** * Accde un objet du schema. * @param id Une chaine de caractres reprsentant l'id d'un objet du schema. * @return SchemaObject Un objet du schema. */ public SchemaObject getObject(String id) { if (contains(id)) { return objets.get(id); } return null; } /** * Retourne un objet du schma dont le nom est name. * @param name Le nom d'un objet, et non son id. * @return SchemaObject Un objet du schma. */ public SchemaObject getObjectByName(String name) { SchemaObject result = null; Enumeration<SchemaObject> it = objets.elements(); while (result == null && it.hasMoreElements()) { SchemaObject o = it.nextElement(); String oName = o.getName(); if (oName == null) { continue; } if (oName.toLowerCase().equals(name.toLowerCase())) { result = o; continue; } String oNameFirst = o.getNameFirstValue(); if (oNameFirst.toLowerCase().equals(name.toLowerCase())) { result = o; continue; } } return result; } /** * Retourne l'ensemble des objets du schema. * @return SchemaObject[] L'ensemble des objets du schema. */ public SchemaObject[] getObjects() { SchemaObject[] result = new SchemaObject[objets.size()]; int position = 0; for (Enumeration<SchemaObject> e = objets.elements(); e.hasMoreElements();) { result[position] = e.nextElement(); position++; } return result; } /** * Retourne l'ensemble des objets du schema d'un certain type. * @param type Le type des objets selectionner. * @return SchemaObject[] L'ensemble des objets du schema. */ public SchemaObject[] getObjects(String type) { Vector<SchemaObject> v = new Vector<SchemaObject>(); for (Enumeration<SchemaObject> e = objets.elements(); e.hasMoreElements();) { SchemaObject o = e.nextElement(); if (type.equals(o.getType())) { v.add(o); } } SchemaObject[] result = new SchemaObject[v.size()]; int position = 0; for (Enumeration<SchemaObject> e = v.elements(); e.hasMoreElements();) { result[position] = e.nextElement(); position++; } return result; } /** * Retourne l'ensemble des objets du schema dans l'ordre dans lequel * ils ont t ajout au schma. * @return SchemaObject[] L'ensemble des objets du schema. */ public SchemaObject[] getObjectsInOrder() { Vector<SchemaObject> result = new Vector<SchemaObject>(); for (SchemaObject o : this.getObjectsInOrder(this.getSyntax().getObjectIdentifierType())) { result.add(o); } for (SchemaObject o : this.getObjectsInOrder(this.getSyntax().getAttributeType())) { result.add(o); } for (SchemaObject o : this.getObjectsInOrder(this.getSyntax().getObjectClassType())) { result.add(o); } return result.toArray(new SchemaObject[10]); } /** * Retourne l'ensemble des objets du schema d'un certain type, dans l'ordre * dans lequel ils ont t ajout au schma. * @param type Le type des objets selectionner. * @return SchemaObject[] L'ensemble des objets du schema. */ public SchemaObject[] getObjectsInOrder(String type) { Vector<SchemaObject> v = new Vector<SchemaObject>(); for (Enumeration<Object> e = objectsOrder.elements(); e.hasMoreElements();) { SchemaObject o = (SchemaObject) e.nextElement(); if (type.equals(o.getType())) { v.add(o); } } SchemaObject[] result = new SchemaObject[v.size()]; int position = 0; for (Enumeration<SchemaObject> e = v.elements(); e.hasMoreElements();) { result[position] = e.nextElement(); position++; } if (type.equals(this.getSyntax().getObjectIdentifierType())) { Properties oids = getObjectsIdentifiers(result); String[] oidsk = getSortedObjectsIdentifiersKeys(oids); result = new SchemaObject[oidsk.length]; for (int i = 0; i < oidsk.length; i++) { for (Enumeration<SchemaObject> e = v.elements(); e.hasMoreElements();) { SchemaObject o = e.nextElement(); String[] okeys = o.getKeys(); if (okeys[0].compareTo(oidsk[i]) == 0) { result[i] = o; } } } } return result; } /** * Returns objects identifiers. * @return Properties All objects identifiers. */ public Properties getObjectsIdentifiers() { return getObjectsIdentifiers(this.getObjects(this.getSyntax().getObjectIdentifierType())); } /** * Returns objects identifiers. * @param oids SchemaObject array * @return Properties All objects identifiers. */ public static Properties getObjectsIdentifiers(SchemaObject[] oids) { Properties objectsIdentifiers = new Properties(); for (SchemaObject object : oids) { String[] keys = object.getKeys(); SchemaValue value = object.getValue(keys[0]); objectsIdentifiers.setProperty(keys[0], value.toString()); } return objectsIdentifiers; } /** * Get sorted object identifiers keys, to loop on object identifiers * into a valid order. * @param oids Object identifiers. * @return String[] Sorted keys */ public static String[] getSortedObjectsIdentifiersKeys(Properties oids) { Hashtable<String, String> ht = new Hashtable<String, String>(); for (Enumeration keys = oids.propertyNames(); keys.hasMoreElements();) { String k = (String) keys.nextElement(); Oid o = new Oid(oids.getProperty(k)); String v = o.toString(); String p = o.getPrefix(); while (p != null) { v = v.replaceFirst(p + ":", oids.getProperty(p) + "."); p = (new Oid(oids.getProperty(p))).getPrefix(); } ht.put(v, k); } String[] st = ht.keySet().toArray(new String[0]); Arrays.sort(st); String[] result = new String[st.length]; int result_index = 0; for (String k : st) { result[result_index] = ht.get(k); result_index++; } return result; } /** * Get objects sorted. * @return SchemaObject[] All schema objects sorted. */ public SchemaObject[] getObjectsSorted() { SchemaObject[] objects = new SchemaObject[objets.size()]; int position = 0; for (Enumeration<SchemaObject> e = objets.elements(); e.hasMoreElements(); position++) { objects[position] = e.nextElement(); } return objects; } /** * Retourne les proprits du schma. * @return Properties L'ensemble des proprits du schma. */ public Properties getProperties() { return proprietes; } /** * Retourne la syntaxe utilise par le schema. * @return SchemaSyntax Une syntaxe spcifique. */ public SchemaSyntax getSyntax() { return syntax; } /** * Return a syntax object by name. */ public static SchemaSyntax getSyntax(String name) { try { String packageName = getSyntaxPackageName(); for (String syntaxe : getSyntaxes()) { Class object = Class.forName(packageName + "." + syntaxe); Field field = object.getField("SHORTNAME"); if (field != null && name.equals(field.get(null).toString())) { @SuppressWarnings("unchecked") SchemaSyntax o = ((Class<SchemaSyntax>) Class.forName(packageName + "." + syntaxe)) .newInstance(); return o; } } for (String syntaxe : getSyntaxes()) { if (name.equals(syntaxe)) { @SuppressWarnings("unchecked") SchemaSyntax o = ((Class<SchemaSyntax>) Class.forName(packageName + "." + syntaxe)) .newInstance(); return o; } } } catch (Exception e) { e.printStackTrace(); } return null; } /** * Retourne le nom du paquetage contenant toutes les syntaxes. * @return String Un nom de paquetage. */ public static String getSyntaxPackageName() { Schema s = new Schema("", null); return s.getClass().getPackage().getName() + ".syntax"; } /** * Retourne l'ensemble des syntaxes connues, qui sont * contenues dans le package 'ldap.syntax'. * @return String[] L'ensemble des noms de classes de syntaxes. */ public static String[] getSyntaxes() { String[] result = null; try { String packageName = getSyntaxPackageName(); URL url = Schema.class.getResource("/" + packageName.replace('.', '/')); if (url == null) { return null; } if (url.getProtocol().equals("jar")) { Vector<String> vectTmp = new Vector<String>(); int index = url.getPath().indexOf('!'); String path = URLDecoder.decode(url.getPath().substring(index + 1), "UTF-8"); JarFile jarFile = new JarFile(URLDecoder.decode(url.getPath().substring(5, index), "UTF-8")); if (path.charAt(0) == '/') { path = path.substring(1); } Enumeration<JarEntry> jarFiles = jarFile.entries(); while (jarFiles.hasMoreElements()) { JarEntry tmp = jarFiles.nextElement(); // // Pour chaque fichier dans le jar, on regarde si c'est un // fichier de classe Java. // if (!tmp.isDirectory() && tmp.getName().substring(tmp.getName().length() - 6).equals(".class") && tmp.getName().startsWith(path)) { int i = tmp.getName().lastIndexOf('/'); String classname = tmp.getName().substring(i + 1, tmp.getName().length() - 6); vectTmp.add(classname); } } jarFile.close(); result = new String[vectTmp.size()]; for (int i = 0; i < vectTmp.size(); i++) { result[i] = vectTmp.elementAt(i); } } else if (url.getProtocol().equals("file")) { // // On cr le fichier associ pour parcourir son contenu. // En l'occurence, c'est un dossier. // File[] files = (new File(url.toURI())).listFiles(); // // On liste tous les fichiers qui sont dedans. // On les stocke dans un vecteur ... // Vector<File> vectTmp = new Vector<File>(); for (File f : files) { if (!f.isDirectory()) { vectTmp.add(f); } } // // ... pour ensuite les mettres dans le tableau de resultat. // result = new String[vectTmp.size()]; for (int i = 0; i < vectTmp.size(); i++) { String name = vectTmp.elementAt(i).getName(); int a = name.indexOf('.'); name = name.substring(0, a); result[i] = name; } } } catch (Exception e) { e.printStackTrace(); } if (result != null) { Arrays.sort(result); } return result; } /** * Return syntaxes short name. */ public static String[] getSyntaxeNames() { return getSyntaxeNames(getSyntaxes()); } /** * Return syntaxes short name. */ public static String[] getSyntaxeNames(String[] names) { String[] syntaxes = names; try { String packageName = getSyntaxPackageName(); for (int i = 0; i < syntaxes.length; i++) { Class object = Class.forName(packageName + "." + syntaxes[i]); Field field = object.getField("SHORTNAME"); if (field != null) { syntaxes[i] = field.get(null).toString(); } } } catch (Exception e) { e.printStackTrace(); } return syntaxes; } /** * Teste si la syntaxe changer depuis la dernire fois qu'on a appel * cette mthode. * @return boolean */ public boolean isSyntaxChangedSinceLastTime() { if (isSyntaxChanged) { isSyntaxChanged = false; return true; } return false; } /** * Permet de notifier que les donnes ont changes. * Tous les objets observant le schema verront la notification. */ public void notifyUpdates() { this.notifyUpdates(false); } /** * Permet de notifier que les donnes ont changes. * Tous les objets observant le schema verront la notification. * @param boolean force Indicates wheter or not to force the update. */ public void notifyUpdates(boolean force) { setChanged(); notifyObservers(Boolean.valueOf(force)); } /** * Set a name for this schema. * @param String A name. */ public void setName(String name) { this.name = name; } /** * Modify objects identifiers of this schema. * @param newOIDs New objects identifiers. */ public void setObjectsIdentifiers(Properties newOIDs) { // Now delete existing oid. SchemaObject[] oids = this.getObjectsInOrder(this.getSyntax().getObjectIdentifierType()); for (SchemaObject object : oids) { this.delObject(object.getId()); } // And reimport the new one. for (Enumeration keys = newOIDs.propertyNames(); keys.hasMoreElements();) { String id = (String) keys.nextElement(); SchemaValue v = this.getSyntax().createSchemaValue(this.getSyntax().getObjectIdentifierType(), id, newOIDs.getProperty(id)); SchemaObject o = this.getSyntax().createSchemaObject(this.getSyntax().getObjectIdentifierType(), v.toString()); o.addValue(id, v); this.addObject(o); } } /** * Modifies les proprits du schma. * @param newProp Le nouvel objet Properties. */ public void setProperties(Properties newProp) { this.proprietes = newProp; } /** * Modifie la syntaxe du schma. * @param newSyntax Une syntaxe spcifique. */ public void setSyntax(SchemaSyntax newSyntax) { isSyntaxChanged = true; syntax = newSyntax; } }