KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > usermanager > JahiaGroupManagerLDAPProvider


1 /*
2  * ____.
3  * __/\ ______| |__/\. _______
4  * __ .____| | \ | +----+ \
5  * _______| /--| | | - \ _ | : - \_________
6  * \\______: :---| : : | : | \________>
7  * |__\---\_____________:______: :____|____:_____\
8  * /_____|
9  *
10  * . . . i n j a h i a w e t r u s t . . .
11  *
12  *
13  *
14  * ----- BEGIN LICENSE BLOCK -----
15  * Version: JCSL 1.0
16  *
17  * The contents of this file are subject to the Jahia Community Source License
18  * 1.0 or later (the "License"); you may not use this file except in
19  * compliance with the License. You may obtain a copy of the License at
20  * http://www.jahia.org/license
21  *
22  * Software distributed under the License is distributed on an "AS IS" basis,
23  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24  * for the rights, obligations and limitations governing use of the contents
25  * of the file. The Original and Upgraded Code is the Jahia CMS and Portal
26  * Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
27  * Ltd. owns the copyrights in the portions it created. All Rights Reserved.
28  *
29  * The Shared Modifications are Jahia View Helper.
30  *
31  * The Developer of the Shared Modifications is Jahia Solution S�rl.
32  * Portions created by the Initial Developer are Copyright (C) 2002 by the
33  * Initial Developer. All Rights Reserved.
34  *
35  * Contributor(s):
36  * ??-???-200?, UNI Lausanne, Viceic Predrag : Initial version
37  * 20-AUG-2003, Jahia Solutions Sarl, Fulco Houkes
38  *
39  * ----- END LICENSE BLOCK -----
40  */

41
42 package org.jahia.services.usermanager;
43
44 import org.jahia.data.JahiaDOMObject;
45 import org.jahia.exceptions.JahiaException;
46 import org.jahia.exceptions.JahiaInitializationException;
47 import org.jahia.exceptions.database.JahiaDatabaseException;
48 import org.jahia.registries.ServicesRegistry;
49 import org.jahia.services.cache.Cache;
50 import org.jahia.services.cache.CacheFactory;
51 import org.jahia.services.database.JahiaIncrementorsDBService;
52 import org.jahia.services.sites.JahiaSite;
53 import org.jahia.services.sites.JahiaSiteTools;
54 import org.jahia.settings.SettingsBean;
55 import org.jahia.utils.JahiaTools;
56
57 import javax.naming.*;
58 import javax.naming.directory.*;
59 import java.io.File JavaDoc;
60 import java.io.FileInputStream JavaDoc;
61 import java.io.FileNotFoundException JavaDoc;
62 import java.io.IOException JavaDoc;
63 import java.sql.Connection JavaDoc;
64 import java.sql.ResultSet JavaDoc;
65 import java.sql.SQLException JavaDoc;
66 import java.sql.Statement JavaDoc;
67 import java.util.*;
68
69
70 /**
71  * <p>Title: </p>
72  * <p>Description: </p>
73  * <p>Copyright: Copyright (c) 2003</p>
74  * <p>Company: </p>
75  *
76  * @author Viceic Predrag <Predrag.Viceic@ci.unil.ch>
77  * @version 1.0
78  */

79
80 public class JahiaGroupManagerLDAPProvider extends JahiaGroupManagerProvider {
81
82     /** logging */
83     private static org.apache.log4j.Logger logger =
84             org.apache.log4j.Logger.getLogger (JahiaGroupManagerLDAPProvider.class);
85
86     private final String JavaDoc MSG_INTERNAL_ERROR = "Group Manager internal error";
87
88     /** the Group Manager unique instance */
89     private static JahiaGroupManagerLDAPProvider instance;
90
91     // the LDAP Group cache name.
92
public static final String JavaDoc LDAP_GROUP_CACHE = "LDAPGroupsCache";
93
94     /** the overall provider Group cache name. */
95     public static final String JavaDoc PROVIDERS_GROUP_CACHE = "ProvidersGroupsCache";
96
97     private Cache mGroupCache;
98     private Cache mProvidersGroupCache;
99
100     private JahiaIncrementorsDBService mIncrementorService = null;
101     public static final String JavaDoc USERS_GROUPNAME = null;
102     public static final String JavaDoc ADMINISTRATORS_GROUPNAME = null;
103     public static final String JavaDoc GUEST_GROUPNAME = null;
104
105     public static final String JavaDoc PROVIDER_NAME = "ldap";
106
107     private static String JavaDoc DEFAULT_CONFIGURATION_FILE = "groups.ldap.properties";
108
109     private static String JavaDoc CONTEXT_FACTORY_PROP = "groups.ldap.context.factory";
110     private static String JavaDoc LDAP_URL_PROP = "groups.ldap.url";
111     private static String JavaDoc AUTHENTIFICATION_MODE_PROP = "groups.ldap.authentification.mode";
112     private static String JavaDoc PUBLIC_BIND_DN_PROP = "groups.ldap.public.bind.dn";
113     private static String JavaDoc PUBLIC_BIND_PASSWORD_PROP = "groups.ldap.public.bind.password";
114
115     private static String JavaDoc PRELOAD_GROUP_MEMBERS = "groups.ldap.preload";
116
117     private static String JavaDoc SEARCH_ATTRIBUTE_PROP = "groups.ldap.search.attribute";
118     private static String JavaDoc SEARCH_NAME_PROP = "groups.ldap.search.name";
119     private static String JavaDoc GROUP_OBJECTCLASS_ATTRIBUTE = "groups.ldap.search.objectclass";
120     private static String JavaDoc DYNGROUP_OBJECTCLASS_ATTRIBUTE = "groups.ldap.dynamic.search.objectclass";
121
122     private static String JavaDoc SEARCH_COUNT_LIMIT_PROP = "groups.ldap.search.countlimit";
123     private static String JavaDoc SEARCH_WILDCARD_ATTRIBUTE_LIST = "groups.ldap.search.wildcards.attributes";
124
125     private static String JavaDoc GROUP_MEMBERS_ATTRIBUTE = "groups.ldap.members.attribute";
126     private static String JavaDoc DYNGROUP_MEMBERS_ATTRIBUTE = "groups.ldap.dynamic.members.attribute";
127
128     private static String JavaDoc LDAP_REFFERAL_PROP = "groups.ldap.refferal";
129
130     /**
131      * Added to handle the fact that the attribute used to define group users is
132      * not always a DN or named as a DN...
133      */

134     private static String JavaDoc SEARCH_USER_ATTRIBUTE_NAME = "groups.ldap.members.user.attibute.map";
135
136     private Properties ldapProperties = null;
137
138     private DirContext publicCtx = null;
139     private boolean connectedToPublic = false;
140     private Vector searchWildCardAttributeList = null;
141
142     //in order to avoid the continuous LDAP lookups due to lookupGroup("administrators:0,1,..")
143
private Vector nonExistentGroups = null;
144
145     // Reference to the provider containing users of this group provider
146
private JahiaUserManagerLDAPProvider userProvider;
147
148     /**
149      * Default constructor.
150      *
151      * @throws JahiaException Raise a JahiaException when during initialization
152      * one of the needed services could not be instanciated.
153      */

154     protected JahiaGroupManagerLDAPProvider ()
155             throws JahiaException {
156
157         // instanciates the cache
158
mGroupCache = CacheFactory.createCache (LDAP_GROUP_CACHE);
159         mProvidersGroupCache = CacheFactory.createCache(PROVIDERS_GROUP_CACHE);
160
161         nonExistentGroups = new Vector ();
162         nonExistentGroups.add ("administrators");
163         nonExistentGroups.add ("guest");
164         nonExistentGroups.add ("users");
165
166         ServicesRegistry registry = ServicesRegistry.getInstance ();
167         if (registry != null) {
168             mIncrementorService = registry.getJahiaIncrementorsDBService ();
169             if (mIncrementorService == null) {
170                 throw new JahiaException (MSG_INTERNAL_ERROR,
171                         "Group manager could not get the Incrementors DB Service instance.",
172                         JahiaException.SERVICE_ERROR,
173                         JahiaException.CRITICAL_SEVERITY);
174             }
175         } else {
176             throw new JahiaException (MSG_INTERNAL_ERROR,
177                     "Group manager could not get the Service Registry instance.",
178                     JahiaException.REGISTRY_ERROR,
179                     JahiaException.CRITICAL_SEVERITY);
180         }
181     }
182
183     /**
184      * Return the unique instance of the Group Manager Service.
185      *
186      * @return the instance of the Group Manager Service.
187      */

188     public static JahiaGroupManagerLDAPProvider getInstance () {
189         if (instance == null) {
190             try {
191                 instance = new JahiaGroupManagerLDAPProvider ();
192
193             } catch (JahiaException ex) {
194                 logger.warn (
195                         "Could not create an instance of the JahiaGroupManagerLDAPProvider class");
196             }
197         }
198         return instance;
199     }
200
201
202     // @author AK
203
/**
204      * Get all JahiaSite objects where the user has an access.
205      *
206      * @param user the user you want to get his access grantes sites list.
207      *
208      * @return Return a vector containing all JahiaSite objects where the user has an access.
209      */

210
211     public Vector getAdminGrantedSites (JahiaUser user)
212             throws org.jahia.exceptions.JahiaException {
213         Vector grantedSites = new Vector ();
214         Enumeration sitesList = ServicesRegistry.getInstance ().
215                 getJahiaSitesService ().getSites ();
216
217         while (sitesList.hasMoreElements ()) {
218             JahiaSite jahiaSite = (JahiaSite) sitesList.nextElement ();
219             logger.debug ("check granted site " + jahiaSite.getServerName ());
220
221             if (JahiaSiteTools.getAdminGroup (jahiaSite).isMember (user)) {
222                 logger.debug ("granted site for " + jahiaSite.getServerName ());
223                 grantedSites.add (jahiaSite);
224             }
225         }
226
227         return grantedSites;
228
229     }
230
231     /**
232      * @param parm1
233      *
234      * @return
235      *
236      * @throws org.jahia.exceptions.JahiaException
237      *
238      */

239     public JahiaDOMObject getAppRoleGroupsAsDOM (int parm1)
240             throws org.jahia.exceptions.JahiaException {
241         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
242         throw new java.lang.UnsupportedOperationException JavaDoc (
243                 "Method getAppRoleGroupsAsDOM() not yet implemented.");
244     }
245
246     /**
247      * This function checks on a gived site if the groupname has already been
248      * assigned to another group.
249      *
250      * @param siteID the site id
251      * @param name String representing the unique group name.
252      *
253      * @return Return true if the specified username has not been assigned yet,
254      * return false on any failure.
255      */

256
257     public boolean groupExists (int siteID, String JavaDoc name) {
258         return (lookupGroup (siteID, name) != null);
259     }
260
261     /**
262      * Return an instance of the guest group
263      *
264      * @return Return the instance of the guest group. Return null on any failure.
265      */

266
267     public JahiaGroup getGuestGroup (int siteID) {
268         if (GUEST_GROUPNAME != null)
269             return lookupGroup (siteID, GUEST_GROUPNAME);
270         else
271             return null;
272
273     }
274
275     /**
276      * Return a <code>Vector</code) of <code>String</code> representing all the
277      * group names of a site.
278      *
279      * @param siteID the site id
280      *
281      * @return Return a vector of strings containing all the group names.
282      */

283
284     public Vector getGroupnameList (int siteID) {
285         Vector result = new Vector ();
286
287         try {
288
289             NamingEnumeration answer = getGroups (getPublicContext (false), null);
290             while (answer.hasMore ()) {
291                 SearchResult sr = (SearchResult) answer.next ();
292                 JahiaGroup curGroup = ldapToJahiaGroup (sr);
293                 if (curGroup != null) {
294                     result.add (curGroup.getGroupname ());
295                 }
296             }
297         } catch (SizeLimitExceededException slee) {
298             // we just return the list as it is
299
logger.debug ("Search generated more than configured maximum search limit in " +
300                     DEFAULT_CONFIGURATION_FILE +
301                     ", limiting to " +
302                     this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) +
303                     " first results...");
304         } catch (NamingException ne) {
305             logger.warn ("JNDI warning",ne);
306             invalidatePublicCtx ();
307             result = new Vector ();
308         }
309
310         return result;
311     }
312
313     /**
314      * Remove the specified user from all the membership lists of all the groups.
315      *
316      * @param user Reference on an existing user.
317      *
318      * @return Return true on success, or false on any failure.
319      */

320
321     public synchronized boolean removeUserFromAllGroups (JahiaUser user) {
322         if (user != null && PROVIDER_NAME.equals(user.getProviderName())) {
323             return false;
324         }
325         return true;
326     }
327
328     /**
329      * Return the list of groups to which the specified user has access.
330      *
331      * @param user Valid reference on an existing group.
332      *
333      * @return Return a vector of strings holding all the group names to
334      * which the user as access. On any error, the returned vector
335      * might be empty.
336      */

337
338     public Vector getUserMembership (JahiaUser user) {
339         if (! (user instanceof JahiaLDAPUser)) {
340             return new Vector();
341         }
342
343         Vector result = ((JahiaLDAPUser)user).getGroups();
344         if (result != null) {
345             return result;
346         }
347
348         result = new Vector ();
349
350         StringBuffer JavaDoc filterBuffer = new StringBuffer JavaDoc ();
351         filterBuffer.append ("(&(objectclass=");
352         filterBuffer.append (ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.
353                 GROUP_OBJECTCLASS_ATTRIBUTE, "groupOfNames"));
354         filterBuffer.append (")(");
355         filterBuffer.append (ldapProperties.getProperty (GROUP_MEMBERS_ATTRIBUTE)); //memberUid
356
filterBuffer.append ("="); //=
357
filterBuffer.append ( ((JahiaLDAPUser) user).getDN() ); //user
358
filterBuffer.append ("))");
359
360         SearchControls searchCtl = new SearchControls ();
361         searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE);
362         String JavaDoc[] retattrs = new String JavaDoc[1];
363         retattrs[0] = ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP);
364         searchCtl.setReturningAttributes (retattrs);
365         NamingEnumeration answer = null;
366         try {
367
368             answer = getGroups(getPublicContext (false), searchCtl, filterBuffer);
369
370             while (answer.hasMore ()) {
371                 String JavaDoc groupKey = ((SearchResult) answer.nextElement ()).
372                         getAttributes ().
373                         get (ldapProperties.getProperty (
374                                 SEARCH_ATTRIBUTE_PROP)).get ().
375                         toString ();
376                 result.add ("{ldap}"+groupKey);
377                 logger.debug ("groupKey=" + groupKey);
378             }
379         } catch (NamingException e) {
380             logger.warn (e);
381             invalidatePublicCtx ();
382             return new Vector ();
383         }
384
385         // Now look for dynamic groups
386
filterBuffer = new StringBuffer JavaDoc ();
387         filterBuffer.append ("(objectclass=");
388         filterBuffer.append (ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.
389                 DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs"));
390         filterBuffer.append (")");
391
392         searchCtl = new SearchControls ();
393         searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE);
394         answer = null;
395
396         try {
397
398             answer = getGroups(getPublicContext (false), searchCtl, filterBuffer);
399
400             while (answer.hasMore ()) {
401                 SearchResult sr = (SearchResult) answer.nextElement ();
402                 Attributes attr = sr.getAttributes ();
403                 String JavaDoc groupKey = attr.
404                         get (ldapProperties.getProperty (
405                                 SEARCH_ATTRIBUTE_PROP)).get ().
406                         toString ();
407
408                 logger.debug ("groupKey=" + groupKey);
409                 NamingEnumeration answer2 = null;
410                 Attribute attribute = attr.get (ldapProperties.getProperty (DYNGROUP_MEMBERS_ATTRIBUTE, "memberurl"));
411                 if (attribute != null) {
412                     answer2 = attribute.getAll ();
413                     while (answer2.hasMore ()) {
414                         String JavaDoc url = (String JavaDoc)answer2.next ();
415                         Properties p = new Properties();
416                         p.put("ldap.url", url);
417                         p.put("user.key", removeKeyPrefix(user.getUserKey()));
418                         Set JavaDoc t = getUserManagerProvider().searchUsers(0,p);
419                         if (!t.isEmpty()) {
420                             result.add("{ldap}"+groupKey);
421                             if (answer2.hasMore()) {
422                                 answer2.close();
423                             }
424                             break;
425                         }
426                     }
427                 }
428             }
429         } catch (NamingException e) {
430             logger.warn (e);
431             invalidatePublicCtx ();
432             return new Vector ();
433         }
434         ((JahiaLDAPUser)user).setGroups(result);
435         return result;
436     }
437
438     // @author NK
439
/**
440      * Return a <code>Vector</code) of <code>String</code> representing all the
441      * group keys of a site.
442      *
443      * @return Return a vector of identifier of all groups of this site.
444      */

445     public Vector getGroupList () {
446         Vector result = new Vector ();
447
448         try {
449
450             NamingEnumeration answer = getGroups (getPublicContext (false), null);
451             while (answer.hasMore ()) {
452                 SearchResult sr = (SearchResult) answer.next ();
453                 JahiaGroup curGroup = ldapToJahiaGroup (sr);
454                 if (curGroup != null) {
455                     result.add (curGroup.getGroupKey ());
456                 }
457             }
458         } catch (SizeLimitExceededException slee) {
459             // we just return the list as it is
460
logger.debug ("Search generated more than configured maximum search limit in " +
461                     DEFAULT_CONFIGURATION_FILE +
462                     ", limiting to " +
463                     this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) +
464                     " first results...");
465         } catch (NamingException ne) {
466             logger.warn ("JNDI warning",ne);
467             invalidatePublicCtx ();
468             result = new Vector ();
469         }
470
471         return result;
472
473     }
474
475     public JahiaDOMObject getUserGroupAccessAsDOM (int parm1)
476             throws org.jahia.exceptions.JahiaException {
477         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
478         throw new java.lang.UnsupportedOperationException JavaDoc (
479                 "Method getUserGroupAccessAsDOM() not yet implemented.");
480     }
481
482     /**
483      * Lookup the group information from the underlaying system (DB, LDAP, ... )
484      * Try to lookup the group into the cache, if it's not in the cache, then
485      * load it into the cahce from the database.
486      *
487      * EP : 2004/23/07 : big refactoring
488      *
489      * @param groupKey Group's unique identification key.
490      *
491      * @return Return a reference on a the specified group name. Return null
492      * if the group doesn't exist or when any error occured.
493      */

494     public JahiaGroup lookupGroup (String JavaDoc groupKey) {
495 // String tmpGroupKey = removeKeyPrefix (groupKey);
496

497         /* 2004-16-06 : update by EP
498         new cache to browse : cross providers ... */

499         JahiaGroup group = (JahiaGroup) mProvidersGroupCache.get ("k"+groupKey);
500         if (group == null) {
501             // 2004-23-07 : use wrappers
502
JahiaGroupWrapper jgw = (JahiaGroupWrapper) mGroupCache.get ("k"+groupKey);
503             if (jgw == null) {
504                 //logger.debug(" group with key=" + tmpGroupKey + " is not found in cache");
505
group = lookupGroupInLDAP (removeKeyPrefix(groupKey));
506
507                 if (group != null) {
508                     /* 2004-16-06 : update by EP
509                     new cache to populate : cross providers ... */

510                     mProvidersGroupCache.put ("k"+groupKey, group);
511                     // with name for speed
512
mProvidersGroupCache.put ("n"+group.getSiteID()+"_"+group.getGroupname (), group);
513                     // 2004-23-07 : store wrappers
514
mGroupCache.put("n"+group.getSiteID()+"_"+group.getGroupname (), new JahiaGroupWrapper(group));
515                 }
516                 // 2004-23-07 : store wrappers
517
mGroupCache.put("k"+groupKey, new JahiaGroupWrapper(group));
518             } else {
519                 group = jgw.getGroup();
520             }
521         }
522         return group;
523     }
524
525     public JahiaGroup getAdministratorGroup (int siteID) {
526         if (ADMINISTRATORS_GROUPNAME != null)
527             return lookupGroup (siteID, ADMINISTRATORS_GROUPNAME);
528         else
529             return null;
530
531     }
532
533     /**
534      * Return a <code>Vector</code) of <code>String</code> representing all the
535      * group names.
536      *
537      * @return Return a vector of strings containing all the group names.
538      */

539
540     public Vector getGroupnameList () {
541         return getGroupList ();
542     }
543
544
545     /**
546      * @param parm1
547      *
548      * @return
549      *
550      * @throws JahiaException
551      */

552     public JahiaDOMObject getAppGroupAccessAsDOM (int parm1)
553             throws JahiaException {
554         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
555         throw new java.lang.UnsupportedOperationException JavaDoc (
556                 "Method getAppGroupAccessAsDOM() not yet implemented.");
557     }
558
559
560     // @author NK
561
/**
562      * Return a <code>Vector</code) of <code>String</code> representing all the
563      * group keys of a site.
564      *
565      * @param siteID the site id
566      *
567      * @return Return a vector of identifier of all groups of this site.
568      */

569
570     public Vector getGroupList (int siteID) {
571         return getGroupList ();
572     }
573
574     public JahiaDOMObject getGroupsAsDOM (int parm1)
575             throws org.jahia.exceptions.JahiaException {
576         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
577         throw new java.lang.UnsupportedOperationException JavaDoc (
578                 "Method getGroupsAsDOM() not yet implemented.");
579     }
580
581     public JahiaDOMObject getGroupPropsAsDOM (int parm1)
582             throws org.jahia.exceptions.JahiaException {
583         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
584         throw new java.lang.UnsupportedOperationException JavaDoc (
585                 "Method getGroupPropsAsDOM() not yet implemented.");
586     }
587
588     /**
589      * Return an instance of the users group.
590      *
591      * @return Return the instance of the users group. Return null on any failure
592      */

593
594     public JahiaGroup getUsersGroup (int siteID) {
595         if (USERS_GROUPNAME != null)
596             return lookupGroup (siteID, USERS_GROUPNAME);
597         else
598             return null;
599
600     }
601
602     /**
603      * Lookup the group information from the underlaying system (DB, LDAP, ... )
604      * Try to lookup the group into the cache, if it's not in the cache, then
605      * load it into the cahce from the database.
606      *
607      * EP : 2004/23/07 : big refactoring
608      *
609      * @param siteID the site id
610      * @param name Group's unique identification name.
611      *
612      * @return Return a reference on a the specified group name. Return null
613      * if the group doesn't exist or when any error occured.
614      */

615     public JahiaGroup lookupGroup (int siteID, String JavaDoc name) {
616         // try to avoid a NullPointerException
617
if (!isNameValid (name)) {
618             return null;
619         }
620
621 // String tmpGroupName = removeKeyPrefix (name);
622

623         /* 2004-16-06 : update by EP
624         new cache to browse : cross providers ... */

625         JahiaGroup group = (JahiaGroup) mProvidersGroupCache.get ("n"+siteID+"_"+name);
626         if (group == null) {
627             // 2004-23-07 : use wrappers
628
JahiaGroupWrapper jgw = (JahiaGroupWrapper) mGroupCache.get ("n"+siteID+"_"+name);
629             if (jgw == null) {
630                 group = lookupGroupInLDAP (siteID, name);
631                 if (group != null) {
632                     /* 2004-16-06 : update by EP
633                     new cache to populate : cross providers ... */

634                     mProvidersGroupCache.put ("k"+group.getGroupKey(), group);
635                     // with name for speed
636
mProvidersGroupCache.put ("n"+group.getSiteID()+"_"+group.getGroupname (), group);
637                     // 2004-23-07 : use wrappers
638
mGroupCache.put("k"+group.getGroupKey (), new JahiaGroupWrapper(group));
639                 }
640                 // 2004-23-07 : use wrappers
641
mGroupCache.put("n"+siteID+"_"+name, new JahiaGroupWrapper(group));
642             } else {
643                 group = jgw.getGroup();
644             }
645         }
646
647         return group;
648     }
649
650     /**
651      * Find groups according to a table of name=value properties. If the left
652      * side value is "*" for a property then it will be tested against all the
653      * properties. ie *=test* will match every property that starts with "test"
654      *
655      * @param siteID site identifier
656      * @param searchCriterias a Properties object that contains search criterias
657      * in the format name,value (for example "*"="*" or "groupname"="*test*") or
658      * null to search without criterias
659      *
660      * @return Set a set of JahiaGroup elements that correspond to those
661      * search criterias, or an empty one if an error has occured. Note this will
662      * only return the configured limit of groups at maxium. Check out the
663      * groups.ldap.properties file to change the limit.
664      */

665     public Set JavaDoc searchGroups (int siteID, Properties searchCriterias) {
666         Set JavaDoc result = new HashSet ();
667
668         // first let's lookup the user by the properties in Jahia's DB
669
try {
670             Set JavaDoc groupKeys = searchLDAPGroupsByDBProperties(siteID,
671                 searchCriterias);
672             // now that we have the keys, let's load all the users.
673
Iterator groupKeyEnum = groupKeys.iterator();
674             while (groupKeyEnum.hasNext()) {
675                 String JavaDoc curGroupKey = (String JavaDoc) groupKeyEnum.next();
676                 JahiaGroup group = lookupGroup(curGroupKey);
677                 result.add(group);
678             }
679
680         } catch (JahiaDatabaseException jde) {
681             logger.error("Error while trying to search for groups by properties",
682                          jde);
683         }
684
685         // now we can search in the LDAP.
686
try {
687             NamingEnumeration ldapGroups = getGroups (getPublicContext (false), searchCriterias);
688             while (ldapGroups.hasMore ()) {
689                 SearchResult sr = (SearchResult) ldapGroups.next ();
690                 JahiaLDAPGroup group = ldapToJahiaGroup (sr);
691                 if (group != null) {
692                     result.add (group);
693                 }
694             }
695
696         } catch (SizeLimitExceededException slee) {
697             logger.debug ("Search generated more than configured maximum search limit in " +
698                     DEFAULT_CONFIGURATION_FILE +
699                     ", limiting to " +
700                     this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) +
701                     " first results...");
702         } catch (PartialResultException pre) {
703             logger.warn (pre);
704         } catch (NamingException ne) {
705             logger.warn ("JNDI warning",ne);
706             invalidatePublicCtx ();
707             result = new HashSet ();
708         }
709         return result;
710     }
711
712     /**
713      * Create a new group in the system.
714      *
715      * @param siteID the site owner of this user
716      * @param groupname Group's unique identification name
717      *
718      * @return Retrun a reference on a group object on success, or if the groupname
719      * already exists or another error occured, null is returned.
720      */

721
722     public synchronized JahiaGroup createGroup (int parm1, String JavaDoc parm2,
723                                                 Properties parm3) {
724         /**@todo Implement this org.jahia.services.usermanager.JahiaGroupManagerProvider abstract method*/
725         throw new java.lang.UnsupportedOperationException JavaDoc (
726                 "Method createGroup() not yet implemented.");
727     }
728
729     public void updateCache(JahiaGroup jahiaGroup) {
730         mGroupCache.put("k"+jahiaGroup.getGroupKey(), new JahiaGroupWrapper(jahiaGroup));
731         mGroupCache.put("n"+jahiaGroup.getSiteID()+"_"+jahiaGroup.getGroupname(), new JahiaGroupWrapper(jahiaGroup));
732         mProvidersGroupCache.put ("k"+jahiaGroup.getGroupKey(), jahiaGroup);
733         mProvidersGroupCache.put ("n"+jahiaGroup.getSiteID()+"_"+jahiaGroup.getGroupname(), jahiaGroup);
734     }
735
736     private void invalidatePublicCtx () {
737         try {
738             invalidateCtx (getPublicContext(false));
739         } catch (NamingException ne) {
740             logger.error("Couldn't invalidate public LDAP context", ne);
741         }
742     }
743
744     private void invalidateCtx (DirContext ctx) {
745         if (ctx == null) {
746             logger.debug ("Context passed is null, ignoring it...");
747             return;
748         }
749         try {
750             ctx.close ();
751         } catch (Exception JavaDoc e) {
752             logger.warn (e);
753         } finally {
754             ctx = null;
755         }
756     }
757
758     /**
759      * Returns the internal public context variable. The point of this is to
760      * keep this connection open as long as possible, in order to reuser the
761      * connection.
762      *
763      * @param boolean forceRefresh.
764      *
765      * @return DirContext the current public context.
766      */

767     public DirContext getPublicContext (boolean forceRefresh) throws NamingException {
768         if (forceRefresh || publicCtx == null) {
769             // this shouldn't happen... but timeouts have to be checked.
770
try {
771                 publicCtx = connectToPublicDir ();
772             } catch (NamingException ne) {
773                 logger.warn ("JNDI warning",ne);
774                 publicCtx = null;
775             }
776             if (publicCtx == null) {
777                 logger.debug ("reconnect failed, returning null context...");
778                 // we've tried everything, still can't connect...
779
return null;
780             }
781         }
782         return publicCtx;
783     }
784
785     /**
786      * EP : 2004/07/05
787      */

788     private boolean isContextValid(DirContext ctx) {
789         try {
790             ctx.getEnvironment();
791             return true;
792         } catch (NamingException ne) {
793             logger.debug ("Reconnection is required... ", ne);
794         } catch (NullPointerException JavaDoc npe) {
795             logger.debug ("Reconnection is required... ", npe);
796         }
797
798         return false;
799     }
800
801     private DirContext connectToPublicDir ()
802             throws NamingException {
803         // EP : 2004/29/06 : implement reconnection mechanism on ldap...
804
if (((JahiaGroupManagerRoutingService)ServicesRegistry
805                             .getInstance()
806                             .getJahiaGroupManagerService())
807                             .getServerList(PROVIDER_NAME) != null) {
808             logger.debug("connecting to all public dir for groups");
809             return connectToAllPublicDir();
810         }
811
812         // Identify service provider to use
813
logger.debug ("Attempting connection to LDAP repository on " +
814                 ldapProperties.getProperty (LDAP_URL_PROP) + "...");
815         Hashtable publicEnv = new Hashtable (11);
816         publicEnv.put (Context.INITIAL_CONTEXT_FACTORY,
817                 ldapProperties.getProperty (CONTEXT_FACTORY_PROP));
818         publicEnv.put (Context.PROVIDER_URL,
819                 ldapProperties.getProperty (LDAP_URL_PROP));
820         publicEnv.put (Context.SECURITY_AUTHENTICATION,
821                 ldapProperties.getProperty (AUTHENTIFICATION_MODE_PROP));
822         publicEnv.put (Context.SECURITY_PRINCIPAL,
823                 ldapProperties.getProperty (PUBLIC_BIND_DN_PROP));
824         publicEnv.put (Context.REFERRAL,
825                 ldapProperties.getProperty (LDAP_REFFERAL_PROP, "ignore"));
826         if (ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP) != null) {
827             logger.debug ("Using authentification mode to connect to public dir...");
828             publicEnv.put (Context.SECURITY_CREDENTIALS,
829                     ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP));
830         }
831
832         // Create the initial directory context
833
return new InitialDirContext (publicEnv);
834     }
835
836     private DirContext connectToAllPublicDir ()
837             throws NamingException {
838         DirContext ctx = null;
839     TreeSet servers = ((JahiaGroupManagerRoutingService)ServicesRegistry
840                             .getInstance()
841                             .getJahiaGroupManagerService())
842                             .getServerList(PROVIDER_NAME);
843
844     for (Iterator ite = servers.iterator(); ite.hasNext();) {
845         ServerBean sb = (ServerBean) ite.next();
846         String JavaDoc sbUrl = (String JavaDoc)sb.getPublicConnectionParameters()
847                         .get(Context.PROVIDER_URL);
848
849         int tryNumber = 1;
850         while (tryNumber <= sb.getMaxReconnection()) {
851                 // Identify service provider to use
852
logger.debug ("Attempting connection "
853                             + tryNumber
854                             + " to LDAP repository on "
855                             + sbUrl
856                             + "...");
857
858                 // Create the initial directory context
859
try {
860                     ctx = new InitialDirContext (sb.getPublicConnectionParameters());
861                     if (isContextValid(ctx))
862                             return ctx;
863                 } catch (NamingSecurityException nse) {
864                     // exception while athenticating, forward the exception...
865
return null;
866                 } catch (NamingException ne) {
867                     // all others exception lead to try another connection...
868
logger.error("Erreur while getting public context on " + sbUrl, ne);
869                 }
870                 tryNumber++;
871         }
872     }
873
874     if (ctx == null) {
875         throw new NamingException("All servers used without success...");
876     }
877
878         return ctx;
879     }
880
881     /**
882      * Retrieves groups from the LDAP public repository.
883      *
884      * @param ctx the current context in which to search for the group
885      * @param filters a set of name=value string that contain RFC 2254 format
886      * filters in the value, or null if we want to look in the full repository
887      *
888      * @return NamingEnumeration a naming enumeration of SearchResult objects
889      * that contains the LDAP group entries that correspond to the filter
890      *
891      * @throws NamingException
892      */

893     private NamingEnumeration getGroups (DirContext ctx, Properties filters)
894             throws NamingException {
895
896         if (ctx == null) {
897             throw new NamingException ("Context is null !");
898         }
899
900         StringBuffer JavaDoc filterString = new StringBuffer JavaDoc ("(|(objectClass="+
901                 ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.GROUP_OBJECTCLASS_ATTRIBUTE, "groupOfNames") +
902                 ")(objectClass="+
903                 ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs") +
904                 "))");
905
906         if (filters == null) {
907             filters = new Properties ();
908         }
909
910         // let's translate Jahia properties to LDAP properties
911
mapJahiaPropertiesToLDAP (filters);
912
913         if (filters.size () > 0) {
914
915             filterString.insert(0,"(&");
916
917             Enumeration filterKeys = filters.keys ();
918             while (filterKeys.hasMoreElements ()) {
919                 String JavaDoc filterName = (String JavaDoc) filterKeys.nextElement ();
920                 String JavaDoc filterValue = filters.getProperty (filterName);
921                 // we do all the RFC 2254 replacement *except* the "*" character
922
// since this is actually something we want to use.
923
filterValue = JahiaTools.replacePattern (filterValue, "\\",
924                         "\\5c");
925                 filterValue = JahiaTools.replacePattern (filterValue, "(",
926                         "\\28");
927                 filterValue = JahiaTools.replacePattern (filterValue, ")",
928                         "\\29");
929
930                 if ("*".equals (filterName)) {
931                     // we must match the value for all the attributes
932
// declared in the property file.
933
if (this.searchWildCardAttributeList != null) {
934                         if (this.searchWildCardAttributeList.size () > 1) {
935                             filterString.append ("(|");
936                         }
937                         Enumeration attributeEnum = this.
938                                 searchWildCardAttributeList.elements ();
939                         while (attributeEnum.hasMoreElements ()) {
940                             String JavaDoc curAttributeName = (String JavaDoc)
941                                     attributeEnum.nextElement ();
942                             filterString.append ("(");
943                             filterString.append (curAttributeName);
944                             filterString.append ("=");
945                             filterString.append (filterValue);
946                             filterString.append (")");
947                         }
948                         if (this.searchWildCardAttributeList.size () > 1) {
949                             filterString.append (")");
950                         }
951                     }
952                 } else {
953                     filterString.append ("(");
954                     filterString.append (filterName);
955                     filterString.append ("=");
956                     filterString.append (filterValue);
957                     filterString.append (")");
958                 }
959             }
960
961             filterString.append (")");
962         }
963
964         SearchControls searchCtl = new SearchControls ();
965         searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE);
966         int countLimit = Integer.parseInt (ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP));
967         searchCtl.setCountLimit (countLimit);
968         return getGroups(ctx, searchCtl, filterString);
969     }
970
971     private NamingEnumeration getGroups(DirContext ctx, SearchControls searchCtl, StringBuffer JavaDoc filterString) throws NamingException {
972         // Search for objects that have those matching attributes
973
logger.debug ("Using filter string [" + filterString.toString () + "]...");
974         try {
975             return ctx.search (
976                     ldapProperties.getProperty (SEARCH_NAME_PROP),
977                     filterString.toString (),
978                     searchCtl);
979         } catch (NoInitialContextException nice) {
980             logger.warn("Reconnection required", nice);
981             return getGroups(getPublicContext(true), searchCtl, filterString);
982         } catch (CannotProceedException cpe) {
983             logger.warn("Reconnection required", cpe);
984             return getGroups(getPublicContext(true), searchCtl, filterString);
985         } catch (ServiceUnavailableException sue) {
986             logger.warn("Reconnection required", sue);
987             return getGroups(getPublicContext(true), searchCtl, filterString);
988         } catch (TimeLimitExceededException tlee) {
989             logger.warn("Reconnection required", tlee);
990             return getGroups(getPublicContext(true), searchCtl, filterString);
991         } catch (CommunicationException ce) {
992             logger.warn("Reconnection required", ce);
993             return getGroups(getPublicContext(true), searchCtl, filterString);
994         }
995     }
996
997     /**
998      * Translates LDAP attributes to a JahiaGroup properties set. Multi-valued
999      * attribute values are converted to Strings containing LINEFEED (\n)
1000     * characters. This way it is quite simple to use String Tokenizers to
1001     * extract multiple values. Note that if a value ALREADY contains a line
1002     * feed characters this will cause unexpected behavior.
1003     *
1004     * @param sr result of a search on a LDAP directory context
1005     * @return JahiaLDAPGroup a group initialized with the properties loaded
1006     * from the LDAP database, or null if no groupKey could be determined for
1007     * the group.
1008     */

1009    private JahiaLDAPGroup ldapToJahiaGroup (SearchResult sr) {
1010        JahiaLDAPGroup group;
1011        Properties groupProps = new Properties ();
1012        String JavaDoc usingGroupKey = null;
1013        Attributes attrs = sr.getAttributes ();
1014
1015        Enumeration attrsEnum = attrs.getAll ();
1016        while (attrsEnum.hasMoreElements ()) {
1017            Attribute curAttr = (Attribute) attrsEnum.nextElement ();
1018            String JavaDoc attrName = curAttr.getID ();
1019            StringBuffer JavaDoc attrValueBuf = new StringBuffer JavaDoc ();
1020            try {
1021                Enumeration curAttrValueEnum = curAttr.getAll ();
1022                while (curAttrValueEnum.hasMoreElements ()) {
1023                    Object JavaDoc curAttrValueObj = curAttrValueEnum.nextElement ();
1024                    if ((curAttrValueObj instanceof String JavaDoc)) {
1025                        attrValueBuf.append ((String JavaDoc) curAttrValueObj);
1026                    } else {
1027                        logger.debug ("Converting attribute <" + attrName + "> from class " +
1028                                curAttrValueObj.getClass ().toString () + " to String...");
1029                        /** @todo FIXME : for the moment we convert everything to String */
1030                        attrValueBuf.append (curAttrValueObj);
1031                    }
1032                    attrValueBuf.append ('\n');
1033                }
1034            } catch (NamingException ne) {
1035                logger.warn ("JNDI warning",ne);
1036                attrValueBuf = new StringBuffer JavaDoc ();
1037            }
1038            String JavaDoc attrValue = attrValueBuf.toString ();
1039            if (attrValue.endsWith ("\n")) {
1040                attrValue = attrValue.substring (0, attrValue.length () - 1);
1041            }
1042            if ((attrName != null) && (attrValue != null)) {
1043                if (usingGroupKey == null) {
1044                    if (attrName.equals (ldapProperties.getProperty (
1045                            SEARCH_ATTRIBUTE_PROP))) {
1046                        usingGroupKey = attrValue;
1047                    }
1048                }
1049                groupProps.setProperty (attrName, attrValue);
1050                // hack for strange-case server
1051
if (attrName.equalsIgnoreCase("objectClass")) {
1052                    groupProps.setProperty ("objectClass", attrValue);
1053                }
1054            }
1055        }
1056
1057        if (usingGroupKey != null) {
1058            mapLDAPToJahiaProperties (groupProps);
1059            // FIXME : Quick hack for merging Jahia DB group properties with LDAP group
1060
mapDBToJahiaProperties (groupProps, usingGroupKey);
1061            boolean dynamic = groupProps.getProperty("objectClass").indexOf(ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs")) != -1;
1062            try {
1063                if (ldapProperties.getProperty(PRELOAD_GROUP_MEMBERS, "true").equalsIgnoreCase("true")) {
1064                    Hashtable members = null;
1065                    try {
1066                        members = getGroupMembers (sr, dynamic);
1067                    } catch (NamingException ne) {
1068                        logger.warn ("JNDI warning",ne);
1069                    }
1070
1071                    group = new JahiaLDAPGroup (0, usingGroupKey, usingGroupKey, 0,
1072                            members,
1073                            groupProps, dynamic, true);
1074                } else {
1075                    group = new JahiaLDAPGroup (0, usingGroupKey, usingGroupKey, 0,
1076                            new Hashtable(),
1077                            groupProps, dynamic, false);
1078                }
1079                return group;
1080            } catch (JahiaException e) {
1081                logger.warn (e);
1082                return null;
1083            }
1084        } else {
1085            logger.debug ("Ignoring entry " + sr.getName () +
1086                    " because it has no valid " +
1087                    ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP) +
1088                    " attribute to be mapped onto user key...");
1089            return null;
1090        }
1091    }
1092
1093    /**
1094     * Map LDAP properties to Jahia group properties.
1095     * This method modifies the groupProps object passed on parameters to add
1096     * the new properties.
1097     *
1098     * @param groupProps Group properties to check for mappings. Basically what
1099     * we do is copy LDAP properties to standard Jahia properties. This is
1100     * defined in the group ldap properties file. Warning this object is modified
1101     * by this method !
1102     *
1103     * @todo FIXME : if properties exist in LDAP that have the same name as
1104     * Jahia properties these will be erased. We should probably look into
1105     * making the properties names more unique such as org.jahia.propertyname
1106     */

1107    private void mapLDAPToJahiaProperties (Properties groupProps) {
1108        // copy attribute to standard Jahia properties if they exist both in
1109
// the mapping and in the repository
1110
for (Iterator iterator = ldapProperties.keySet().iterator(); iterator.hasNext();) {
1111            String JavaDoc key = (String JavaDoc) iterator.next();
1112            if (key.endsWith(".attribute.map")) {
1113                String JavaDoc jahiaProperty = key.substring(12,key.length()-14);
1114                String JavaDoc curProperty = ldapProperties.getProperty(key);
1115                if (groupProps.getProperty (curProperty) != null) {
1116                    groupProps.setProperty (jahiaProperty, groupProps.getProperty (curProperty));
1117                }
1118            }
1119        }
1120    }
1121
1122    /**
1123     * Retrieves properties from internal jahia DB
1124     *
1125     * @param groupProps the group properties to set
1126     * @param usingGroupKey the group whose the properties has to be extracted.
1127     */

1128    private void mapDBToJahiaProperties (Properties groupProps,
1129                                         String JavaDoc usingGroupKey) {
1130        try {
1131            // Get all the user attributes
1132

1133            Properties dbProperties = JahiaGroupDBUtils.getInstance ().getGroupProperties (
1134                    -1, PROVIDER_NAME, usingGroupKey);
1135            groupProps.putAll (dbProperties);
1136        } catch (JahiaException je) {
1137            logger.debug ("SQL Exception occured : Could not read the group [" +
1138                    usingGroupKey + "] from the database for site LDAP group");
1139            // FIXME -Fulco- : Don't know yet what to do with this exception.
1140
// It should be logged somewhere !
1141
}
1142
1143    }
1144
1145    /**
1146     * Maps Jahia group to LDAP properties using the definition
1147     * mapping in the group LDAP configuration properties file. This modifies
1148     * the groupProps
1149     *
1150     * @param groupProps
1151     */

1152    private void mapJahiaPropertiesToLDAP (Properties groupProps) {
1153        for (Iterator iterator = ldapProperties.keySet().iterator(); iterator.hasNext();) {
1154            String JavaDoc key = (String JavaDoc) iterator.next();
1155            if (key.endsWith(".attribute.map")) {
1156                String JavaDoc jahiaProperty = key.substring(12,key.length()-14);
1157                String JavaDoc curProperty = ldapProperties.getProperty(key);
1158                if (groupProps.getProperty (jahiaProperty) != null) {
1159                    groupProps.put(curProperty, groupProps.remove(jahiaProperty));
1160                }
1161            }
1162        }
1163        if (groupProps.containsKey("members")) {
1164            groupProps.put(ldapProperties.get(GROUP_MEMBERS_ATTRIBUTE), groupProps.remove("members"));
1165        }
1166    }
1167
1168    private String JavaDoc removeKeyPrefix (String JavaDoc groupKey) {
1169        if (groupKey.startsWith ("{ldap}")) {
1170            return groupKey.substring (6);
1171        } else {
1172            return groupKey;
1173        }
1174    }
1175
1176    private JahiaLDAPGroup lookupGroupInLDAP (String JavaDoc groupKey) {
1177        JahiaLDAPGroup group = null;
1178        Enumeration enumeration = nonExistentGroups.elements ();
1179
1180        logger.debug("lookupGroupInLDAP :: " + groupKey);
1181
1182        //FIXME: lousy solution for avoiding the over-querying of the ldap for non-existent groups...
1183
while (enumeration.hasMoreElements ()) {
1184            if (groupKey.indexOf (enumeration.nextElement () + ":") != -1)
1185                return group;
1186        }
1187        //
1188
try {
1189            SearchResult sr = getPublicGroup (getPublicContext (false), groupKey);
1190            if (sr == null) {
1191                return null;
1192            }
1193            group = ldapToJahiaGroup (sr);
1194
1195        } catch (SizeLimitExceededException slee) {
1196            logger.warn ("Search generated more than configured maximum search limit in " +
1197                    DEFAULT_CONFIGURATION_FILE +
1198                    ", limiting to " +
1199                    this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) +
1200                    " first results...");
1201            group = null;
1202
1203        } catch (PartialResultException pre) {
1204            logger.warn (pre);
1205        } catch (NamingException ne) {
1206            logger.warn ("JNDI warning",ne);
1207            invalidatePublicCtx ();
1208            group = null;
1209        }
1210        return group;
1211    }
1212
1213    /**
1214     * Retrieves a group from the LDAP public repository.
1215     *
1216     * @param ctx the current context in which to search for the group
1217     * @param cn the unique identifier for the group
1218     *
1219     * @return a SearchResult object, which is the *first* result matching the
1220     * cn
1221     *
1222     * @throws NamingException
1223     */

1224    private SearchResult getPublicGroup (DirContext ctx, String JavaDoc cn)
1225            throws NamingException {
1226
1227        Properties filters = new Properties ();
1228
1229        filters.setProperty (ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP),
1230                cn);
1231        NamingEnumeration answer = getGroups (ctx, filters);
1232        SearchResult sr = null;
1233        if (answer.hasMore ()) {
1234            // we only take the first value if there are multiple answers, which
1235
// should normally NOT happend if the groupKey is unique !!
1236
sr = (SearchResult) answer.next ();
1237
1238            boolean hasMore = false;
1239            try {
1240                hasMore = answer.hasMore ();
1241            } catch (PartialResultException pre) {
1242                logger.warn (pre);
1243            }
1244
1245            if (hasMore) {
1246                // there is at least a second result.
1247
// throw new NamingException("GroupLDAPService.getPublicGroup>" +
1248
// "Warning : multiple group with same groupKey in LDAP repository.");
1249
logger.info ("Warning : multiple groups with same CN in LDAP repository.");
1250            }
1251        }
1252        return sr;
1253    }
1254
1255    private boolean isNameValid (String JavaDoc name) {
1256
1257        if (name == null) {
1258            return false;
1259        }
1260
1261        if (name.length () == 0) {
1262            return false;
1263        }
1264
1265        String JavaDoc authorizedCharacters =
1266                " -abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789{}";
1267        /* EP : 2004-17-06
1268        char[] chars = authorizedCharacters.toCharArray ();
1269        char[] nameBuffer = name.toCharArray ();*/

1270
1271        boolean badCharFound = false;
1272        for (int i = 0; i < name.length() && !badCharFound; i++) {
1273            badCharFound = authorizedCharacters.indexOf((int)name.charAt(i)) < 0;
1274            if (badCharFound) {
1275                logger.debug ("Bad character found in ldap group name [" +
1276                        name +
1277                        "] at position " + i);
1278            }
1279        }
1280        /* end EP mods */
1281        return (!badCharFound);
1282    }
1283
1284    private JahiaLDAPGroup lookupGroupInLDAP (int siteID, String JavaDoc name) {
1285        JahiaLDAPGroup group = lookupGroupInLDAP (name);
1286        if (group == null) {
1287            return null;
1288        }
1289        group.setSiteID (siteID);
1290        return group;
1291    }
1292
1293    public void init (SettingsBean jSettings)
1294            throws JahiaInitializationException {
1295        String JavaDoc configPath = jSettings.getJahiaLdapDiskPath ();
1296        String JavaDoc configFileName;
1297
1298        File JavaDoc configFile = new File JavaDoc (configPath + File.separator +
1299                DEFAULT_CONFIGURATION_FILE);
1300        if (configFile.exists ()) {
1301
1302            configFileName = configPath + File.separator +
1303                    DEFAULT_CONFIGURATION_FILE;
1304
1305            try {
1306                File JavaDoc ldapPropFile = new File JavaDoc (configFileName);
1307                FileInputStream JavaDoc ldapPropInputStr = new FileInputStream JavaDoc (
1308                        ldapPropFile);
1309                ldapProperties = new Properties ();
1310                ldapProperties.load (ldapPropInputStr);
1311                ldapPropInputStr.close ();
1312            } catch (FileNotFoundException JavaDoc fnfe) {
1313                logger.error ("Error while loading group manager LDAP configuration file",
1314                        fnfe);
1315            } catch (IOException JavaDoc ioe) {
1316                logger.error ("Error while loading group manager LDAP configuration file", ioe);
1317            }
1318
1319        } else {
1320            logger.debug ("Config file not found in " + configPath +
1321                    File.separator + DEFAULT_CONFIGURATION_FILE);
1322        }
1323
1324        try {
1325            getPublicContext (true);
1326        } catch (NamingException ne) {
1327            logger.error (
1328                    "Error while initializing public browsing connection to LDAP repository",
1329                    ne);
1330            invalidatePublicCtx ();
1331        }
1332
1333        String JavaDoc wildCardAttributeStr = ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.
1334                SEARCH_WILDCARD_ATTRIBUTE_LIST);
1335        if (wildCardAttributeStr != null) {
1336            this.searchWildCardAttributeList = new Vector ();
1337            StringTokenizer wildCardTokens = new StringTokenizer (
1338                    wildCardAttributeStr, ", ");
1339            while (wildCardTokens.hasMoreTokens ()) {
1340                String JavaDoc curAttrName = wildCardTokens.nextToken ().trim ();
1341                this.searchWildCardAttributeList.add (curAttrName);
1342            }
1343        }
1344
1345        logger.debug ("Initialized and connected to public repository");
1346    }
1347
1348    /**
1349     * Modified by EP : 2004-18-06
1350     * Changes the way to retrieve groups members.
1351     * The properties file indicates a value for the attribute name that is stored
1352     * into the GROUP_MEMBERS_ATTRIBUTE, the use it instead of parsing the DN
1353     */

1354    private Hashtable getGroupMembers (SearchResult sr, boolean dynamic)
1355            throws NamingException {
1356        Hashtable members = new Hashtable ();
1357        Attributes attr = sr.getAttributes ();
1358        NamingEnumeration answer = null;
1359        try {
1360            if (dynamic) {
1361                answer = attr.get (ldapProperties.getProperty (
1362                        DYNGROUP_MEMBERS_ATTRIBUTE, "memberurl")).
1363                        getAll ();
1364            } else {
1365                answer = attr.get (ldapProperties.getProperty (
1366                        GROUP_MEMBERS_ATTRIBUTE)).
1367                        getAll ();
1368            }
1369        } catch (NullPointerException JavaDoc ne) {
1370            logger.debug ("No members");
1371        }
1372
1373// // test if the properties file contains the SEARCH_USER_ATTRIBUTE_NAME value
1374
// if (ldapProperties.getProperty(SEARCH_USER_ATTRIBUTE_NAME) == null) {
1375
// logger.error("Missing the attribute type stored in the " + GROUP_MEMBERS_ATTRIBUTE + " group attribute.");
1376
// return members;
1377
// }
1378

1379        // EP : 2004-21-07 : refactoring : uses old way if SEARCH_USER_ATTRIBUTE_NAME not defined
1380
String JavaDoc searchProperties = ldapProperties.getProperty (SEARCH_USER_ATTRIBUTE_NAME);
1381        boolean searchUserDefined = (!(searchProperties == null) && (searchProperties.length() > 0));
1382
1383        logger.debug ("Getting members for group, dynamic="+dynamic+", searchUserDefined="+searchUserDefined);
1384
1385        if (answer != null) {
1386            while (answer.hasMore ()) {
1387                String JavaDoc userKey = (String JavaDoc)answer.next ();
1388                if (dynamic) {
1389                    Properties p = new Properties();
1390                    p.put("ldap.url", userKey);
1391                    Set JavaDoc t = getUserManagerProvider().searchUsers(0,p);
1392                    for (Iterator iterator = t.iterator(); iterator.hasNext();) {
1393                        JahiaUser jahiaUser = (JahiaUser) iterator.next();
1394                        members.put(jahiaUser.getName(), jahiaUser);
1395                    }
1396                } else {
1397                    JahiaUser user = null;
1398                    if (searchUserDefined) { // use attribute definition (?)
1399
user = getUserManagerProvider().
1400                                        lookupUser (userKey,
1401                                        ldapProperties
1402                                        .getProperty (
1403                                        SEARCH_USER_ATTRIBUTE_NAME));
1404                    } else { // use DN
1405
user = getUserManagerProvider()
1406                                        .lookupUserFromDN(
1407                                                userKey);
1408                    }
1409                    if (user != null)
1410                        members.put (user.getName(), user);
1411                }
1412            }
1413        }
1414        return members;
1415    }
1416
1417
1418    public synchronized JahiaUserManagerLDAPProvider getUserManagerProvider() {
1419        if (userProvider == null) {
1420            Vector v = ServicesRegistry.getInstance().getJahiaUserManagerService().getProviderList();
1421            for (Iterator iterator = v.iterator(); iterator.hasNext();) {
1422                UserManagerProviderBean userManagerProviderBean = (UserManagerProviderBean) iterator.next();
1423                if (userManagerProviderBean.getClassName().equals(JahiaUserManagerLDAPProvider.class.getName())) {
1424                    JahiaUserManagerLDAPProvider jahiaUserManagerLDAPProvider = (JahiaUserManagerLDAPProvider)userManagerProviderBean.getInstance();
1425                    if (jahiaUserManagerLDAPProvider.getUrl().equals(ldapProperties.get(LDAP_URL_PROP))) {
1426                        userProvider = jahiaUserManagerLDAPProvider;
1427                    }
1428                }
1429            }
1430        }
1431        return userProvider;
1432    }
1433
1434    /**
1435     * Transforms a search with "*" characters into a valid LIKE statement
1436     * with "%" characters. Also escapes the string to remove all "'" and
1437     * other chars that might disturb the request construct.
1438     *
1439     * @param input the original String
1440     *
1441     * @return String a resulting string that has
1442     */

1443    private String JavaDoc makeLIKEString (String JavaDoc input) {
1444        String JavaDoc result = JahiaTools.replacePattern(input, "*", "%");
1445        result = JahiaTools.replacePattern(result, "'", "\\'");
1446        result = JahiaTools.replacePattern(result, "\"", "\\\"");
1447        result = JahiaTools.replacePattern(result, "_", "\\_");
1448        return result;
1449    }
1450
1451    private synchronized Set JavaDoc searchLDAPGroupsByDBProperties (int siteID,
1452        Properties searchCriterias)
1453        throws JahiaDatabaseException {
1454        Set JavaDoc groupKeys = new HashSet();
1455
1456        // Get a database connection
1457
Connection JavaDoc dbConn = org.jahia.services.database.ConnectionDispenser.
1458                            getConnection();
1459        if (dbConn == null) {
1460            return groupKeys;
1461        }
1462
1463        if (searchCriterias == null) {
1464            searchCriterias = new Properties();
1465            searchCriterias.setProperty("*", "*");
1466        }
1467
1468        boolean haveWildCardProperty = false;
1469        if (searchCriterias.getProperty("*") != null) {
1470            haveWildCardProperty = true;
1471        }
1472
1473        // execute the SELECT query
1474
Statement JavaDoc statement = null;
1475        try {
1476            statement = dbConn.createStatement();
1477            if (statement != null) {
1478
1479                StringBuffer JavaDoc query;
1480
1481                query =
1482                    new StringBuffer JavaDoc(
1483                    "SELECT DISTINCT grpkey_jahia_grp_prop FROM jahia_grp_prop WHERE provider_jahia_grp_prop='");
1484                query.append(PROVIDER_NAME);
1485                query.append("' AND ");
1486                Enumeration criteriaNames = searchCriterias.keys();
1487                while (criteriaNames.hasMoreElements()) {
1488                    String JavaDoc curCriteriaName = (String JavaDoc) criteriaNames.
1489                                             nextElement();
1490                    String JavaDoc curCriteriaValue = makeLIKEString(
1491                        searchCriterias.getProperty(curCriteriaName));
1492                    if ("*".equals(curCriteriaName)) {
1493                        // we must look in all columns
1494
query.append(
1495                            " value_jahia_grp_prop LIKE '");
1496                        query.append(curCriteriaValue);
1497                        query.append("' ");
1498                        if (criteriaNames.hasMoreElements()) {
1499                            query.append(" AND ");
1500                        }
1501                    } else {
1502                        query.append(
1503                            "(name_jahia_grp_prop='");
1504                        query.append(makeLIKEString(curCriteriaName));
1505                        query.append(
1506                            "' AND value_jahia_grp_prop LIKE '");
1507                        query.append(curCriteriaValue);
1508                        query.append("') ");
1509                        if (criteriaNames.hasMoreElements()) {
1510                            query.append(" AND ");
1511                        }
1512                    }
1513                }
1514                logger.debug("Executing query [" + query.toString() + "]");
1515
1516                ResultSet JavaDoc rs = statement.executeQuery(query.toString());
1517                if (rs != null) {
1518                    while (rs.next()) {
1519                        String JavaDoc name = rs.getString(1);
1520                        if (name != null) {
1521                            groupKeys.add(name);
1522                        }
1523                    }
1524                }
1525            }
1526        } catch (SQLException JavaDoc ex) {
1527            logger.error("Error while searching groups in site " + siteID, ex);
1528        } finally {
1529            closeStatement(statement);
1530        }
1531
1532        return groupKeys;
1533
1534    }
1535
1536    //-------------------------------------------------------------------------
1537
private void closeStatement (Statement JavaDoc statement)
1538        throws JahiaDatabaseException {
1539        // Close the opened statement
1540
try {
1541            if (statement != null) {
1542                statement.close();
1543            }
1544        } catch (SQLException JavaDoc sqlEx) {
1545            throw new JahiaDatabaseException(
1546                "Could not close a statement in JahiaDBUser",
1547                sqlEx, JahiaDatabaseException.ERROR_SEVERITY);
1548        }
1549    }
1550
1551}
1552
Popular Tags