Lire et écrire sur des annuaires LDAP avec des agents Lotus Notes
Pour effectuer ces d'opérations depuis Lotus Notes, j'utilise des agents Java sur mon annuaire.
Voici le code simplifié de cet agent. Il renseigne, sur un autre annuaire LDAP (par exemple l'annuaire LDAP Windows)
le champ "OU", en y mettant la valeur du champ "Service" de l'annuaire Lotus Notes, en me basant sur la clé "Nom-Prénom".
Voici le code simplifié de cet agent. Il renseigne, sur un autre annuaire LDAP (par exemple l'annuaire LDAP Windows)
le champ "OU", en y mettant la valeur du champ "Service" de l'annuaire Lotus Notes, en me basant sur la clé "Nom-Prénom".
import lotus.domino.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Map;
import java.lang.String;
public class LectureLDAP extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
Log log = session.createLog("EcritureNotesVersLDAP");
log.openFileLog("d:/Lotus/AMgr_Log/EcritureLDAP_Telephonique.txt");
AgentContext agentContext = session.getAgentContext();
Database db;
db = agentContext.getCurrentDatabase();
log.logAction("Démarrage de l'agent");
java.util.Hashtable env = new java.util.Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://NomDuServeurLDAP:389/");
// ici j'indique que je me connecte avec authentification : user + mot de passe env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=Compte LDAP,o=directory"); // user
env.put(Context.SECURITY_CREDENTIALS, "MotDePasse"); // mot de passe
DirContext ctx = new InitialDirContext(env);
log.logAction("Connexion LDAP ok");
ModificationItem[] mods = new ModificationItem[1];
View vue = db.getView("(Personnes)");
Document doc = vue.getFirstDocument();
while (doc != null)
{
String nom = doc.getItemValueString("LastName");
String prenom = doc.getItemValueString("FirstName");
String identif = prenom + " " + nom ;
String service = doc.getItemValueString("ServiceL");
NamingEnumeration answer;
String recherche = "o=directory";
String filtre = "(uid=" + identif + ")";
SearchControls ctls = new SearchControls();
// Pour que la recherche porte également sur les sous-niveaux du noeud LDAP
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
log.logAction("Recherche avec filtre = " + filtre + " sur la base " +
recherche); answer = ctx.search( recherche, filtre, ctls);
if (answer.hasMore()) {
try {
// Modification du compte LDAP
Attributes attrs = sr.getAttributes();
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new
BasicAttribute("ou", service)); log.logAction("J'essaie de modifier " + name + " pour mettre ou=" + service); ctx.modifyAttributes(name, mods);
log.logAction("ok !");
}
catch (Exception e4)
{
log.logAction("Erreur lors de la tentative de modification de " + filtre +
" : " + e4);
}
}
else
{
log.logAction("Impossible de trouver "+ prenom + " " + nom + " dans l'annuaire LDAP. Pas de modification effectuée");
}
doc = vue.getNextDocument(doc);
} // fin boucle principale while
log.logAction("Fin normale de l'agent");
} catch(Exception e) { system.out.println("Erreur : " + e); } // fin try
} // fin main
} // fin classe
Le 30/01/2006 - Benoît Colin
Comment superviser l'exécution de tous les agents plannifiés d'un serveur
Difficile, avec Lotus Notes, d'avoir un aperçu général des exécutions de tous les agents planifiés se trouvant sur un serveur. Il faut ouvrir les bases une par une, ouvrir les agents plannifiés un par un pour pouvoir voir quand un agent plannifier doit s'exécuter.
Mon souhait était d'avoir une vision globale de tous les agents du serveur et de leur plannification, afin de me rendre compte des pics de charges liées à l'exécution de ces agents.
Cela a été possible grace à... un agent LotusScript plannifié. Appelons-le "Agent Audit".
Son principe est simple : cet agent parcours toutes les bases du serveur ; pour chacune des bases, il examine les agents qui sont de type "plannifiés"...
Malheureusement, les classes LotusScript ne nous permettent pas d'accèder aux propriétés de plannification d'un agent (c'est à dire si il est exécuté quotidiennement, hebdomadairement, à quelle heure, à quel intervalle...)
Par contre, on peut accèder à une autre information, qui nous sera bien utile : la dernière date d'exécution de l'agent !
Je plannifie mon "Agent Audit" pour qu'il s'exécute toutes les 10 minutes.
Ainsi, régulièrement, cet agent récupére la dernière date d'exécution de tous les agents plannifiés. Ces informations sont enregistrées dans les documents Notes (Date-Heure, Nom de la base Notes, Nom de l'agent, Dernière date d'exécution).
Bon, trèves de bla-bla, voici le code :
Mon souhait était d'avoir une vision globale de tous les agents du serveur et de leur plannification, afin de me rendre compte des pics de charges liées à l'exécution de ces agents.
Cela a été possible grace à... un agent LotusScript plannifié. Appelons-le "Agent Audit".
Son principe est simple : cet agent parcours toutes les bases du serveur ; pour chacune des bases, il examine les agents qui sont de type "plannifiés"...
Malheureusement, les classes LotusScript ne nous permettent pas d'accèder aux propriétés de plannification d'un agent (c'est à dire si il est exécuté quotidiennement, hebdomadairement, à quelle heure, à quel intervalle...)
Par contre, on peut accèder à une autre information, qui nous sera bien utile : la dernière date d'exécution de l'agent !
Agent.LastRun
Je plannifie mon "Agent Audit" pour qu'il s'exécute toutes les 10 minutes.
Ainsi, régulièrement, cet agent récupére la dernière date d'exécution de tous les agents plannifiés. Ces informations sont enregistrées dans les documents Notes (Date-Heure, Nom de la base Notes, Nom de l'agent, Dernière date d'exécution).
Bon, trèves de bla-bla, voici le code :
On Error Goto erreur
Dim session As New NotesSession
Dim currentdb As NotesDatabase
Dim database as Notesdatabase
Dim view As NotesView
Dim doc As NotesDocument
Set currentdb = session.CurrentDatabase
Dim dbdir As New NotesDbDirectory("MonServeur/SVR/MonDomaine")
Set database = dbdir.GetFirstDatabase(DATABASE)
While Not database Is Nothing
TentativeOuverture=True
Call database.Open ("", "")
TentativeOuverture=False
agents = database.Agents
If Not Isempty(agents) Then
Forall a In agents
If a.trigger = TRIGGER_SCHEDULED And a.HasRunSinceModified = True Then
Set doc = db.CreateDocument
doc.form = "DateExecAgent"
doc.Base = database.Title
doc.BaseFichier = ReplaceString(database.FilePath, "\", "/")
doc.Agent = a.Name
doc.DerniereDateExecution = a.LastRun
doc.Serveur = a.ServerName
doc.BaseAgent = ReplaceString(database.FilePath, "\", "/") + "-" + a.Name
Call doc.Save (True, True)
Set doc = db.CreateDocument
doc.form="Agent"
doc.BaseAgent = ReplaceString(db2.FilePath, "\", "/") + "-" + a.Name
Call doc.Save(True, True)
End If
End Forall
End If
BaseSuivante :
Set database = dbdir.GetNextDatabase
Wend
Exit Sub
erreur :
If TentativeOuverture = True Then
Set nlog = db.createdocument
nlog.form="Log"
nlog.Body = "Impossible d'ouvrir la base " & db2.Title & " : " & Error & " ligne " & Str(Erl)
Call nlog.Save (True, True)
Resume BaseSuivante
End If
Messagebox(Error & " à la ligne " & Str(Erl))
Le 27/01/2006 - Benoît Colin
Une vue Lotus Notes 100% html mais néanmoins catégorisée
Le problème
Sous Lotus Notes, l'utilisation de la propriété "Traiter le contenu de la vue comme du code html" interdit en principe d'utiliser les fonctions de déployer-condenser de catégories lors de la consultation de la vue avec le navigateur. En effet, Domino ne génére pas de boutons permettant de déployer une catégorie d'une vue. Comment faire pour obtenir une vue ayant ces fonctions, si la vue est paramétrée comme "Traiter le contenu de la vue comme du code html" ?
La solution
Il est possible de contourner ce problème, grace aux commandes URL Domino. L'appel d'une vue se fait sous la syntaxe suivante :
http://ServeurDomino/BaseLotusNotes.nsf/NomDeLaVue?OpenView
Ou, éventuellement, l'appel peut se faire sur un masque contenant la vue (vue intégrée) :
http://ServeurDomino/BaseLotusNotes.nsf/NomDuMasqueContenantLaVue?OpenForm
La commandes ?OpenForm et ?OpenView acceptent des paramétres facultatifs qui permettent de jouer sur ce qui doit être affiché par la vue :
CollapseView : Condense toutes les catégories
ExpandView : Déploie toutes les catégories
Collapse=<num> : Condense la catégorie identifiée par son numéro <num> dans la vue
Expand=<num> : Déploie la catégorie identifiée par son numéro <num> dans la vue
Start=<num> : N'affiche que les lignes se trouvant sous la ligne <num> incluse
Count=<num> : Nombre de lignes à afficher
<num> pouvant être hiérarchisé, c'est à dire prendre des valeurs comme 2.3.1 ou 1.5.
Ainsi, la commande URL http://ServeurDomino/BaseLotusNotes.nsf/NomDuMasque?OpenForm&Expand=1.5 aura pour effet d'ouvrir la vue et de déployer la cinquieme sous-catégorie de la premiere catégorie.
Si on dispose des données suivantes :
Boissons
Froides
Limonade
Soda
Chaudes
Café
Plats
Froids
Sandwich jambon
Chauds
Steack frites
Tartiflette
La commande URL http://ServeurDomino/BaseLotusNotes.nsf/NomDuMasque?OpenForm&Expand=2.1 ouvrira la vue et déploiera la section "Froids" de la section "Plats".
La commande URL http://ServeurDomino/BaseLotusNotes.nsf/NomDuMasque?OpenForm&Expand=2 ouvrira la vue et déploiera la section "Plats", sans déployer ses sous-catégories.
Dans le design de la vue, il suffit donc d'utiliser le code HTML suivant pour toutes les colonnes catégorisées :
<a href='NomDuMasqueContenantLaVue?Openform&Expand=" + @DocNumber + "'>" + TypeAliment + "</a><br>"
Le code HTML généré par cette vue sera :
<a href='NomDuMasqueContenantLaVue?Openform&Expand=1'>Boissons</a><br>
<a href='NomDuMasqueContenantLaVue?Openform&Expand=1.1'>Froides</a><br>
...
Le résultat : une vue avec catégories, mais que l'on peut personnaliser intégralement car elle est 100% html !
Sympa, non ?
Le 14/12/2005 - Benoit Colin