001/*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: FilteredRole.java,v 1.4 2009/01/28 05:34:50 ww203982 Exp $
026 *
027 * Portions Copyright 2015 ForgeRock AS.
028 */
029
030package com.iplanet.ums;
031
032import java.security.Principal;
033
034import com.iplanet.services.ldap.Attr;
035import com.iplanet.services.ldap.AttrSet;
036import com.iplanet.services.util.I18n;
037import org.forgerock.opendj.ldap.SearchScope;
038
039/**
040 * FilteredRole is a role implementation of the membership interface
041 * IFilteredRole. FilteredRole maps to nsFilteredRoleDefinition of iPlanet
042 * Directory Server.
043 * @supported.api
044 */
045public class FilteredRole extends BaseRole implements IFilteredMembership,
046        IUMSConstants {
047
048    /**
049     * Name of the filter attribute, which controls membership.
050     *
051     * @supported.api
052     */
053    public static final String FILTER_ATTR_NAME = "nsRoleFilter";
054
055    /**
056     * LDAP object classes that define the nsFilteredRoleDefinition, the iPlanet
057     * Directory Server object class that maps to FilteredRole.
058     *
059     * @supported.api
060     */
061    public static final String[] FILTEREDROLE_OBJECTCLASSES = { "top",
062            "ldapsubentry", "nsroledefinition", "nscomplexroledefinition",
063            "nsfilteredroledefinition" };
064
065    /**
066     * The attributes that are required for FilteredRole. Any creation template
067     * for FilteredRole should have these attributes.
068     *
069     * @supported.api
070     */
071    public static final String[] FILTEREDROLE_ATTRIBUTES = { "cn",
072            "nsRoleFilter" };
073
074    private static I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
075
076    /**
077     * No argument constructor
078     */
079    public FilteredRole() {
080    }
081
082    /**
083     * Constructs a FilteredRole object in-memory using the default template
084     * registered for FilteredRole. The save method must be called to save the
085     * new object to persistent storage.
086     * 
087     * @param name
088     *            name for the role
089     * @param filter
090     *            the filter that controls membership
091     * @exception UMSException
092     *                on failure to instantiate
093     */
094    public FilteredRole(String name, String filter) throws UMSException {
095        this(new AttrSet(new Attr("cn", name)));
096    }
097
098    /**
099     * Constructs a FilteredRole object in-memory using the default registered
100     * template for FilteredRole. One needs to call the save method to save the
101     * new object to persistent storage.
102     * 
103     * @param attrSet
104     *            Attribute/value set
105     * @exception UMSException
106     *                on failure to instantiate
107     */
108    FilteredRole(AttrSet attrSet) throws UMSException {
109        this(TemplateManager.getTemplateManager().getCreationTemplate(_class,
110                null), attrSet);
111    }
112
113    /**
114     * Constructs a FilteredRole object in memory
115     * with a given template. The save method must be called to save the new
116     * object to persistent storage.
117     * 
118     * @param template
119     *            Template for creating a group
120     * @param attrSet
121     *            Attribute/value set
122     * @exception UMSException
123     *                on failure to instantiate
124     *
125     * @supported.api
126     */
127    public FilteredRole(CreationTemplate template, AttrSet attrSet)
128            throws UMSException {
129        super(template, attrSet);
130    }
131
132    /**
133     * Sets the filter that controls the membership.
134     * 
135     * @param filter
136     *            the filter that controls the membership
137     * @throws UMSException
138     *             if there is any error while setting the filter
139     *
140     * @supported.api
141     */
142    public void setFilter(String filter) throws UMSException {
143        setAttribute(new Attr(FILTER_ATTR_NAME, filter));
144    }
145
146    /**
147     * Gets the filter that controls the membership.
148     * 
149     * @return the filter that controls the membership
150     * @throws UMSException
151     *             if there is any error while getting the filter
152     *
153     * @supported.api
154     */
155    public String getFilter() throws UMSException {
156        return getAttribute(FILTER_ATTR_NAME).getValue();
157    }
158
159    /**
160     * TO DO : incomplete, fix the logic of building the base and filter Gets
161     * the members of the role
162     * 
163     * @param attributes
164     *            Attributes to return
165     * @return SearchResults for iterating through the unique identifiers of
166     *         members of the role
167     * @throws UMSException
168     *             on failure to search
169     */
170    protected SearchResults getMembers(String[] attributes) throws UMSException
171    {
172        Guid guid = getGuid();
173        String base = guid.getDn();
174        int index = base.indexOf(",");
175        if (index > 0) {
176            base = base.substring(index + 1);
177        }
178        Guid bguid = new Guid(base);
179        Principal principal = getPrincipal();
180        if (principal == null) {
181            throw new IllegalArgumentException(i18n
182                    .getString(IUMSConstants.BAD_PRINCIPAL_HDL));
183        }
184
185        return DataLayer.getInstance().search(principal, bguid,
186                SearchScope.WHOLE_SUBTREE.intValue(), getFilter(), attributes, false, null);
187    }
188
189    /**
190     * TO DO : incomplete, fix the logic of building the base and filter Gets
191     * the members of the role
192     * 
193     * @param attributes
194     *            Attributes to return
195     * @param filter
196     *            an LDAP filter to select a subset of members
197     * @return SearchResults for iterating through the unique identifiers of
198     *         members of the role
199     * @throws InvalidSearchFilterException
200     *             on invalid search filter
201     * @throws UMSException
202     *             on failure to search
203     */
204    protected SearchResults getMembers(String[] attributes, String filter)
205            throws InvalidSearchFilterException, UMSException {
206        Guid guid = getGuid();
207        String base = guid.getDn();
208        int index = base.indexOf(",");
209        if (index > 0) {
210            base = base.substring(index + 1);
211        }
212        Guid bguid = new Guid(base);
213        return DataLayer.getInstance().search(
214                getPrincipal(),
215                bguid,
216                SearchScope.WHOLE_SUBTREE.intValue(),
217                " ( & " + " ( " + getFilter() + ")" + " ( " + filter + " ) "
218                        + " ) ", attributes, false, null);
219    }
220
221    /**
222     * Gets the members of the role.
223     * 
224     * @return SearchResults for iterating through the unique identifiers of
225     *         members of the role
226     * @throws UMSException
227     *             on failure to search
228     *
229     * @supported.api
230     */
231    public SearchResults getMemberIDs() throws UMSException {
232        String[] attributesToGet = { "objectclass" };
233        return getMembers(attributesToGet);
234    }
235
236    /**
237     * Gets the members of the role meeting an LDAP filter
238     * condition.
239     * 
240     * @param filter
241     *            an LDAP filter to select a subset of members
242     * @return SearchResults for iterating through the unique identifiers of
243     *         members of the role
244     * @exception UMSException
245     *                on failure to search
246     *
247     * @supported.api
248     */
249    public SearchResults getMemberIDs(String filter) throws UMSException {
250        String[] attributesToGet = { "objectclass" };
251        return getMembers(attributesToGet, filter);
252    }
253
254    /**
255     * Gets the member count.
256     * 
257     * @return Number of members of the role
258     * @exception UMSException
259     *                on failure to search
260     *
261     * @supported.api
262     */
263    public int getMemberCount() throws UMSException {
264        int count = 0;
265        String[] attributesToGet = { "dn" };
266        SearchResults searchResults = getMembers(attributesToGet);
267        while (searchResults.hasMoreElements()) {
268            searchResults.next().getDN();
269            count++;
270        }
271        return count;
272    }
273
274    /**
275     * Gets a member given an index (zero based).
276     * 
277     * @param index
278     *            Zero-based index into the group container
279     * @return Unique identifier for a member
280     * @exception UMSException
281     *                on failure to search
282     *
283     * @supported.api
284     */
285    public Guid getMemberIDAt(int index) throws UMSException {
286        if (index < 0) {
287            throw new IllegalArgumentException(Integer.toString(index));
288        }
289        String[] attributesToGet = { "dn" };
290        SearchResults searchResults = getMembers(attributesToGet);
291        int srIndex = 0;
292        while (searchResults.hasMoreElements()) {
293            String s = searchResults.next().getDN();
294            if (srIndex == index) {
295                searchResults.abandon();
296                return new Guid(s);
297            }
298            srIndex++;
299        }
300        throw new ArrayIndexOutOfBoundsException(Integer.toString(index));
301    }
302
303    /**
304     * Checks if a given identifier is a member of the role.
305     * 
306     * @param po
307     *            member to be checked for membership
308     * @return <code>true</code> if it is a member
309     * @exception UMSException
310     *                on failure to read object for guid
311     */
312    // public boolean isMember(PersistentObject po)
313    // throws UMSException {
314    // return hasMember(po, true);
315    // }
316    /**
317     * Checks if a given identifier is a member of the role.
318     * 
319     * @param guid
320     *            guid of the member to be checked for membership
321     * @return <code>true</code> if it is a member
322     * @exception UMSException
323     *                on failure to read object for guid
324     *
325     * @supported.api
326     */
327    public boolean hasMember(Guid guid) throws UMSException {
328        Principal principal = getPrincipal();
329        if (principal == null) {
330            throw new IllegalArgumentException(i18n
331                    .getString(IUMSConstants.BAD_PRINCIPAL_HDL));
332        }
333        PersistentObject member = UMSObject.getObject(principal, guid);
334        return hasMember(member);
335    }
336
337    private static final Class _class = com.iplanet.ums.FilteredRole.class;
338}