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: ACI.java,v 1.4 2008/06/25 05:41:38 qcheng Exp $
026 *
027 */
028
029/**
030 * Portions Copyrighted [2011] [ForgeRock AS]
031 */
032package com.iplanet.services.ldap.aci;
033
034import java.util.ArrayList;
035import java.util.Arrays;
036import java.util.Collection;
037import java.util.Iterator;
038
039/**
040 * Class that encapsulates directory entry aci Provides a simple programmatic
041 * interface to compose, set, query and parse ACI
042 * @supported.api
043 */
044public class ACI {
045
046    public static final String ACI = "aci";
047
048    static final String[] SUPPORTED_ATTR_RULES = { "userdnattr", "groupdnattr",
049            "userattr" };
050
051    static final Collection SUPPORTED_ATTR_RULES_COLLECTION = Arrays
052            .asList(SUPPORTED_ATTR_RULES);
053
054    static final String TARGET = "target";
055
056    static final String TARGETFILTER = "targetfilter";
057
058    static final String TARGETATTR = "targetattr";
059
060    static final String TARGETATTRFILTERS = "targetattrfilters";
061
062    static final String VERSION = "version";
063
064    static final String ACL = "acl";
065
066    static final String ALLOW = "allow";
067
068    static final String DENY = "deny";
069
070    static final String USERDN = "userdn";
071
072    static final String GROUPDN = "groupdn";
073
074    static final String ROLEDN = "roledn";
075
076    static final String USERDNATTR = "userdnattr";
077
078    static final String GROUPDNATTR = "groupdnattr";
079
080    static final String USERATTR = "userattr";
081
082    static final String AUTHMETHOD = "authmethod";
083
084    static final String IP = "ip";
085
086    static final String DNS = "dns";
087
088    static final String TIMEOFDAY = "timeofday";
089
090    static final String DAYOFWEEK = "dayofweek";
091
092    static final String PRINCIPAL_SET = "principal";
093
094    static final String AUTHMETHOD_SET = "authmethod";
095
096    static final String IP_SET = "IP";
097
098    static final String TOD_SET = "tod";
099
100    static final String DOW_SET = "dow";
101
102    static final String KEYWORD = "keyword";
103
104    static final String OPERATOR = "operator";
105
106    static final String VALUE = "value";
107
108    static final String OPENPARENTH = "(";
109
110    static final String CLOSEPARENTH = ")";
111
112    static final String EXPRESSIONCONNECTOR = "expressionconnector";
113
114    static final String EQ = "=";
115
116    static final String NE = "!=";
117
118    static final String GE = ">=";
119
120    static final String LE = "<=";
121
122    static final String GT = ">";
123
124    static final String LT = "<";
125
126    static final String AND = "and";
127
128    static final String OR = "or";
129
130    static final String OR_PIPE = "||";
131
132    static final String SPACE = " ";
133
134    static final String QUOTE = "\"";
135
136    static final String NEWLINE = "\n";
137
138    static final String SEMICOLON = ";";
139
140    static final String COMMA = ",";
141
142    static final String LDAP_PREFIX = "ldap:///";
143
144    /*
145     * List of keywords in the context of ACI: Keywords that control the target
146     * set: target targetattr targetfilter targetattrfilters
147     * 
148     * Keywords that control the permissions: allow deny
149     * 
150     * Legal values for permissions: read write add delete search compare
151     * selfwrite proxy all
152     * 
153     * Keywords that are allowed in bindrule: userdn with special values: self
154     * all anyone groupdn userdnattr groupdnattr userattr ip dns timeofday
155     * dayofweek authmethod none simple ssl sasl
156     */
157
158    /**
159     * No argument constructor
160     * @supported.api
161     */
162    public ACI() {
163    }
164
165    /**
166     * Constructor
167     * 
168     * @param name
169     *            name of the ACI
170     * @supported.api
171     */
172    public ACI(String name) {
173        _name = name;
174    }
175
176    /*
177     * Constructor.
178     * 
179     * @param name name of the ACI.
180     * @param target the target to which the ACI applies.
181     * @param tagetFilter the LDAP filter that controls the set of entries to
182     *        which the ACI applies.
183     * @param targetAttributes <code>QualfiedCollection</code> of attributes to
184     *        which the ACI applies.
185     * @param users collection of users for who the ACI applies.
186     * @param permissions <code>QualifiedCollection</code> of permissions that
187     *        apply to the ACI.
188     * @link QualifiedCollection.setExclusive
189     * @supported.api
190     */
191    public ACI(String name, String target, String targetFilter,
192            QualifiedCollection targetAttributes, Collection users,
193            QualifiedCollection permissions) {
194        setName(name);
195        setTarget(target);
196        setTargetFilter(targetFilter);
197        setTargetAttributes(targetAttributes);
198        setUsers(users);
199        setPermissions(permissions);
200    }
201
202    /**
203     * Checks whether the object is passed is semantically equal to this object.
204     * The objects are considered to be equal if both the objects have the same
205     * state, that is their respective instance variables have equal values.
206     * 
207     * @param object
208     *            the object to check for equality
209     * @return <code>true</code> if the passed object is equal to this object,
210     *         <code>false</code> otherwise
211     * @supported.api
212     */
213    public boolean equals(Object object) {
214        boolean objectsEqual = false;
215        if (this == object) {
216            objectsEqual = true;
217        } else if (object != null && object.getClass().equals(getClass())) {
218            ACI castObject = (ACI) object;
219            if (castObject.getName().equals(getName())
220                    && castObject.getTarget().equals(getTarget())
221                    && castObject.getTargetFilter().equals(getTargetFilter())
222                    && castObject.getTargetAttributes().equals(
223                            getTargetAttributes())
224                    && castObject.getPermissions().equals(getPermissions())
225                    && castObject.getUsers().equals(getUsers())
226                    && castObject.getGroups().equals(getGroups())
227                    && castObject.getRoles().equals(getRoles())
228                    && castObject.getClientHostNames().equals(
229                            getClientHostNames())
230                    && castObject.getTimesOfDay().equals(getTimesOfDay())
231                    && castObject.getDaysOfWeek().equals(getDaysOfWeek())
232                    && castObject.getAuthMethods().equals(getAuthMethods())) {
233                objectsEqual = true;
234            }
235        }
236        return objectsEqual;
237    }
238
239    /**
240     * Sets the name of the ACI
241     * 
242     * @param name
243     *            the name of the ACI
244     * @supported.api
245     */
246    public void setName(String name) {
247        _name = name;
248    }
249
250    /**
251     * Gets the name of the ACI
252     * 
253     * @return the name of the ACI
254     * @supported.api
255     */
256    public String getName() {
257        return _name;
258    }
259
260    /**
261     * Sets the target of the ACI
262     * 
263     * @param target
264     *            the target of the ACI
265     * @supported.api
266     */
267    public void setTarget(String target) {
268        _target = target;
269    }
270
271    /**
272     * Gets the target of the ACI
273     * 
274     * @return the target of the ACI
275     * @supported.api
276     */
277    public String getTarget() {
278        return _target;
279    }
280
281    /**
282     * Sets the target filter of the ACI
283     * 
284     * @param targetFilter
285     *            the ldap target filter for the ACI
286     * @supported.api
287     */
288    public void setTargetFilter(String targetFilter) {
289        _targetFilter = targetFilter;
290    }
291
292    /**
293     * Gets the target filter for the ACI
294     * 
295     * @return the target filter that controls the entries to which the ACI
296     *         apllies
297     * @supported.api
298     */
299    public String getTargetFilter() {
300        return _targetFilter;
301    }
302
303    /**
304     * Removes the target filter of the ACI
305     * @supported.api
306     */
307    public void removeTargetFilter() {
308        _targetFilter = null;
309    }
310
311    /**
312     * Sets the QualifiedCollection of targetAttributes that apply to the ACI
313     * 
314     * @param targetAttributes
315     *            the QualifiedCollection of target attributes that apply to the
316     *            ACI
317     * @supported.api
318     */
319    public void setTargetAttributes(QualifiedCollection targetAttributes) {
320        _targetAttributes = targetAttributes;
321    }
322
323    /**
324     * Geets the QualifiedCollection of targetAttributes that apply to the ACI
325     * 
326     * @return the QualifiedCollection of target attributes that apply to the
327     *         ACI
328     * @supported.api
329     */
330
331    public QualifiedCollection getTargetAttributes() {
332        return _targetAttributes;
333    }
334
335    /**
336     * Removes the QualifiedCollection of targetAttributes that contol the
337     * attributes to which this ACI apllies
338     * @supported.api
339     */
340    public void removeTargetAttributes() {
341        _targetAttributes = null;
342    }
343
344    /**
345     * Sets the QualifiedCollection of permissions that apply to the ACI
346     * 
347     * @param permissions
348     *            the QualifiedCollection of permissions that apply to the ACI
349     *           
350     * @supported.api
351     */
352    public void setPermissions(QualifiedCollection permissions) {
353        _permissions = permissions;
354    }
355
356    /**
357     * Geets the QualifiedCollection of permissions that apply to the ACI
358     * 
359     * @return the QualifiedCollection of permissions that apply to the ACI
360     *        
361     * @supported.api
362     */
363    public QualifiedCollection getPermissions() {
364        return _permissions;
365    }
366
367    /**
368     * Sets the collection of users to whom the ACI apllies
369     * 
370     * @param users
371     *            the collection of users to whom the ACI apllies
372     *           
373     * @supported.api
374     */
375    public void setUsers(Collection users) {
376        _users = users;
377    }
378
379    /**
380     * Gets the collection of users to whom the ACI apllies
381     * 
382     * @return the collection of users to whom the ACI apllies
383     *        
384     * @supported.api
385     */
386    public Collection getUsers() {
387        return _users;
388    }
389
390    /**
391     * Sets the collection of groups to whom the ACI apllies
392     * 
393     * @param groups
394     *            the collection of groups to whom the ACI apllies
395     *           
396     * @supported.api
397     */
398    public void setGroups(Collection groups) {
399        _groups = groups;
400    }
401
402    /**
403     * Gets the collection of groups to whom the ACI apllies
404     * 
405     * @return the collection of groups to whom the ACI apllies
406     *        
407     * @supported.api
408     */
409    public Collection getGroups() {
410        return _groups;
411    }
412
413    /**
414     * Sets the collection of roles to which the ACI applies
415     * 
416     * @param roles
417     *            the collection of roles to which the ACI applies
418     *           
419     * @supported.api
420     */
421    public void setRoles(Collection roles) {
422        _roles = roles;
423    }
424
425    /**
426     * Gets the collection of roles to which the ACI applies
427     * 
428     * @return the collection of roles to which the ACI applies
429     *        
430     * @supported.api
431     */
432    public Collection getRoles() {
433        return _roles;
434    }
435
436    /**
437     * Sets the client IPs to which this ACI applies
438     * 
439     * @param clientIP
440     *            collection of client IPs to which this ACI applies
441     *           
442     * @supported.api
443     */
444    public void setClientIP(Collection clientIP) {
445        _clientIP = clientIP;
446    }
447
448    /**
449     * Gets the client IPs to which this ACI applies
450     * 
451     * @return collection of client IPs to which this ACI applies
452     *        
453     * @supported.api
454     */
455    public Collection getClientIP() {
456        return _clientIP;
457    }
458
459    /**
460     * Sets the client DNS host names to which this ACI applies
461     * 
462     * @param clientHostNames
463     *            collection of DNS host names to which this ACI applies
464     *           
465     * @supported.api
466     */
467    public void setClientHostNames(Collection clientHostNames) {
468        _clientHostNames = clientHostNames;
469    }
470
471    /**
472     * Gets the client DNS host names to which this ACI applies
473     * 
474     * @return collection of DNS host names to which this ACI applies
475     *        
476     * @supported.api
477     */
478    public Collection getClientHostNames() {
479        return _clientHostNames;
480    }
481
482    /**
483     * Sets the times of the day at which this ACI applies
484     * 
485     * @param timesOfDay
486     *            collection of timesOfDay at which this ACI applies
487     *           
488     * @supported.api
489     */
490    public void setTimesOfDay(Collection timesOfDay) {
491        _timesOfDay = timesOfDay;
492    }
493
494    /**
495     * Gets the times of the day at which this ACI applies
496     * 
497     * @return collection of timesOfDay at which this ACI applies
498     *        
499     * @supported.api
500     */
501    public Collection getTimesOfDay() {
502        return _timesOfDay;
503    }
504
505    /**
506     * Sets the days of the week on which this ACI applies
507     * 
508     * @param daysOfWeek
509     *            collection of days of week on which this ACI applies
510     *           
511     * @supported.api
512     */
513    public void setDaysOfWeek(Collection daysOfWeek) {
514        _daysOfWeek = daysOfWeek;
515    }
516
517    /**
518     * Gets the days of the week on which this ACI applies
519     * 
520     * @return collection of days of week on which this ACI applies
521     *        
522     * @supported.api
523     */
524    public Collection getDaysOfWeek() {
525        return _daysOfWeek;
526    }
527
528    /**
529     * Sets the authorization methods to which this ACI applies
530     * 
531     * @param authMethods
532     *            the collection of authorization methods to which this ACI
533     *            applies
534     */
535    public void setAuthMethods(Collection authMethods) {
536        _authMethods = authMethods;
537    }
538
539    /**
540     * Gets the authorization methods to which this ACI applies
541     * 
542     * @return collection of authorization methods to which this ACI applies
543     *        
544     * @supported.api
545     */
546    public Collection getAuthMethods() {
547        return _authMethods;
548    }
549
550    /**
551     * Sets the value for the given attrRule name
552     * 
553     * @param attrName
554     *            name of the attribute
555     * @param values
556     *            collections of value for the attr rule
557     * @supported.api
558     */
559    public void setAttrRuleValue(String attrName, Collection values)
560            throws ACIComposeException {
561        attrName = attrName.toLowerCase();
562        if (attrName.equals(USERDNATTR)) {
563            setUserDNAttrs(values);
564        } else if (attrName.equals(GROUPDNATTR)) {
565            setGroupDNAttrs(values);
566        } else if (attrName.equals(USERATTR)) {
567            setUserAttrs(values);
568        } else {
569            throw new ACIComposeException("Unsupported attr rule name : "
570                    + attrName);
571        }
572    }
573
574    /**
575     * Gets the collections of values for the given attrRuleName
576     * 
577     * @return collection of attr rule names supported by the ACI API
578     *        
579     * @supported.api
580     */
581    public Collection getAttrRuleValue(String attrName) throws ACIException {
582        Collection values = null;
583        if (attrName.equals(USERDNATTR)) {
584            values = getUserDNAttrs();
585        } else if (attrName.equals(GROUPDNATTR)) {
586            values = getGroupDNAttrs();
587        } else if (attrName.equals(USERATTR)) {
588            values = getUserAttrs();
589        } else {
590            throw new ACIException("Unsupported attr rule name : " + attrName);
591        }
592        return values;
593    }
594
595    /**
596     * Gets the names of supported attr rule names
597     * 
598     * @return the collection of attr rule names supported by the ACI API
599     *        
600     * @supported.api
601     */
602    public Collection getSupportedAttrRules() {
603        return SUPPORTED_ATTR_RULES_COLLECTION;
604    }
605
606    /**
607     * Sets the target attr filters that controls value based access control
608     * 
609     * @param targetAttrFilters
610     *            string defining a filter for value based access control
611     *           
612     * @supported.api
613     */
614    public void setTargetAttrFilters(String targetAttrFilters) {
615        _targetAttrFilters = targetAttrFilters;
616    }
617
618    /**
619     * Gets the target attr filters that controls value based access control
620     * 
621     * @return string defining a filter for value based access control
622     *        
623     * @supported.api
624     */
625    public String getTargetAttrFilters() {
626        return _targetAttrFilters;
627    }
628
629    /**
630     * Gets a string representation of this ACI
631     * 
632     * @return string representation of this ACI
633     * @supported.api
634     */
635    public String toString() {
636        StringBuilder aci = new StringBuilder();
637        StringBuffer bindRule = new StringBuffer();
638        StringBuffer tempBuffer = new StringBuffer();
639        String value = null;
640
641        value = getTarget();
642        if (value != null && value.length() != 0) {
643            aci.append(SPACE).append(OPENPARENTH).append(TARGET).append(SPACE)
644                    .append(EQ).append(SPACE).append(QUOTE).append(value)
645                    .append(QUOTE).append(CLOSEPARENTH).append(NEWLINE);
646        }
647
648        QualifiedCollection qc = null;
649        Iterator iter = null;
650        boolean exclusive;
651        String operator;
652        qc = getTargetAttributes();
653        if (qc != null && qc.getCollection() != null
654                && !qc.getCollection().isEmpty()) {
655            exclusive = qc.isExclusive();
656            operator = exclusive ? NE : EQ;
657            aci.append(SPACE).append(OPENPARENTH).append(TARGETATTR).append(
658                    SPACE).append(operator).append(SPACE);
659            iter = qc.getCollection().iterator();
660            if (iter.hasNext()) {
661                value = (String) iter.next();
662                aci.append(QUOTE).append(value);
663            }
664            while (iter.hasNext()) {
665                value = (String) iter.next();
666                aci.append(OR_PIPE).append(value);
667            }
668            aci.append(QUOTE).append(CLOSEPARENTH).append(NEWLINE);
669        }
670
671        value = getTargetFilter();
672        if (value != null && value.length() != 0) {
673            aci.append(SPACE).append(OPENPARENTH).append(TARGETFILTER).append(
674                    SPACE).append(EQ).append(SPACE).append(QUOTE).append(value)
675                    .append(QUOTE).append(CLOSEPARENTH).append(NEWLINE);
676        }
677
678        value = getTargetAttrFilters();
679        if (value != null && value.length() != 0) {
680            aci.append(SPACE).append(OPENPARENTH).append(TARGETATTRFILTERS)
681                    .append(SPACE).append(EQ).append(SPACE).append(QUOTE)
682                    .append(value).append(QUOTE).append(CLOSEPARENTH).append(
683                            NEWLINE);
684        }
685
686        aci.append(SPACE).append(OPENPARENTH).append(VERSION).append(SPACE)
687                .append(getVersion()).append(SEMICOLON);
688        aci.append(ACL).append(SPACE).append(QUOTE).append(getName()).append(
689                QUOTE).append(SEMICOLON);
690
691        qc = getPermissions();
692        if (qc != null && qc.getCollection() != null
693                && !qc.getCollection().isEmpty()) {
694            exclusive = qc.isExclusive();
695            String permissionType = exclusive ? DENY : ALLOW;
696            aci.append(permissionType).append(OPENPARENTH);
697            iter = qc.getCollection().iterator();
698            if (iter.hasNext()) {
699                value = (String) iter.next();
700                aci.append(value);
701            }
702            while (iter.hasNext()) {
703                value = (String) iter.next();
704                aci.append(COMMA).append(SPACE).append(value);
705            }
706            aci.append(CLOSEPARENTH).append(NEWLINE);
707        }
708
709        Collection collection = null;
710        collection = getUsers();
711        if (collection != null && !collection.isEmpty()) {
712            iter = collection.iterator();
713            if (iter.hasNext()) {
714                value = (String) iter.next();
715                tempBuffer.append(USERDN).append(EQ).append(QUOTE).append(
716                        LDAP_PREFIX).append(value);
717            }
718            while (iter.hasNext()) {
719                value = (String) iter.next();
720                tempBuffer.append(SPACE).append(OR_PIPE).append(SPACE).append(
721                        LDAP_PREFIX).append(value);
722            }
723            tempBuffer.append(QUOTE).append(SPACE);
724        }
725        if (tempBuffer.length() != 0) {
726            bindRule.append(tempBuffer);
727        }
728
729        tempBuffer.setLength(0);
730        collection = getGroups();
731        if (collection != null && !collection.isEmpty()) {
732            iter = collection.iterator();
733            if (iter.hasNext()) {
734                value = (String) iter.next();
735                tempBuffer.append(GROUPDN).append(EQ).append(QUOTE).append(
736                        LDAP_PREFIX).append(value);
737            }
738            while (iter.hasNext()) {
739                value = (String) iter.next();
740                tempBuffer.append(SPACE).append(OR_PIPE).append(SPACE).append(
741                        LDAP_PREFIX).append(value);
742            }
743            tempBuffer.append(QUOTE).append(SPACE);
744        }
745        if (tempBuffer.length() != 0) {
746            if (bindRule.length() > 0) {
747                bindRule.append(SPACE).append(OR).append(SPACE);
748            }
749            bindRule.append(tempBuffer);
750        }
751
752        tempBuffer.setLength(0);
753        collection = getRoles();
754        if (collection != null && !collection.isEmpty()) {
755            iter = collection.iterator();
756            if (iter.hasNext()) {
757                value = (String) iter.next();
758                tempBuffer.append(ROLEDN).append(EQ).append(QUOTE).append(
759                        LDAP_PREFIX).append(value);
760            }
761            while (iter.hasNext()) {
762                value = (String) iter.next();
763                tempBuffer.append(SPACE).append(OR_PIPE).append(SPACE).append(
764                        LDAP_PREFIX).append(value);
765            }
766            tempBuffer.append(QUOTE).append(SPACE);
767        }
768        if (tempBuffer.length() != 0) {
769            if (bindRule.length() > 0) {
770                bindRule.append(" or ");
771            }
772            bindRule.append(tempBuffer);
773        }
774
775        tempBuffer.setLength(0);
776        collection = getUserDNAttrs();
777        if (collection != null && !collection.isEmpty()) {
778            iter = collection.iterator();
779            if (iter.hasNext()) {
780                value = (String) iter.next();
781                tempBuffer.append(USERDNATTR).append(EQ).append(QUOTE).append(
782                        value).append(QUOTE);
783            }
784            while (iter.hasNext()) {
785                value = (String) iter.next();
786                tempBuffer.append(SPACE).append(OR).append(SPACE);
787                tempBuffer.append(USERDNATTR).append(EQ).append(QUOTE).append(
788                        value).append(QUOTE);
789            }
790        }
791        if (tempBuffer.length() != 0) {
792            if (bindRule.length() > 0) {
793                bindRule.append(SPACE).append(OR).append(SPACE);
794            }
795            bindRule.append(tempBuffer);
796        }
797
798        tempBuffer.setLength(0);
799        collection = getGroupDNAttrs();
800        if (collection != null && !collection.isEmpty()) {
801            iter = collection.iterator();
802            if (iter.hasNext()) {
803                value = (String) iter.next();
804                tempBuffer.append(GROUPDNATTR).append(EQ).append(QUOTE).append(
805                        value).append(QUOTE);
806            }
807            while (iter.hasNext()) {
808                value = (String) iter.next();
809                tempBuffer.append(SPACE).append(OR).append(SPACE);
810                tempBuffer.append(GROUPDNATTR).append(EQ).append(QUOTE).append(
811                        value).append(QUOTE);
812            }
813        }
814        if (tempBuffer.length() != 0) {
815            if (bindRule.length() > 0) {
816                bindRule.append(SPACE).append(OR).append(SPACE);
817            }
818            bindRule.append(tempBuffer);
819        }
820
821        tempBuffer.setLength(0);
822        collection = getUserAttrs();
823        if (collection != null && !collection.isEmpty()) {
824            iter = collection.iterator();
825            if (iter.hasNext()) {
826                value = (String) iter.next();
827                tempBuffer.append(USERATTR).append(EQ).append(QUOTE).append(
828                        value).append(QUOTE);
829            }
830            while (iter.hasNext()) {
831                value = (String) iter.next();
832                tempBuffer.append(SPACE).append(OR).append(SPACE);
833                tempBuffer.append(USERATTR).append(EQ).append(QUOTE).append(
834                        value).append(QUOTE);
835            }
836        }
837        if (tempBuffer.length() != 0) {
838            if (bindRule.length() > 0) {
839                bindRule.append(SPACE).append(OR).append(SPACE);
840            }
841            bindRule.append(tempBuffer);
842        }
843
844        if (bindRule.length() > 0) {
845            bindRule.insert(0, SPACE);
846            bindRule.insert(1, OPENPARENTH);
847            bindRule.append(CLOSEPARENTH).append(NEWLINE);
848        }
849
850        tempBuffer.setLength(0);
851        collection = getAuthMethods();
852        if (collection != null && !collection.isEmpty()) {
853            iter = collection.iterator();
854            if (iter.hasNext()) {
855                value = (String) iter.next();
856                tempBuffer.append(AUTHMETHOD).append(EQ).append(QUOTE).append(
857                        value).append(QUOTE);
858            }
859            while (iter.hasNext()) {
860                value = (String) iter.next();
861                tempBuffer.append(SPACE).append(OR).append(SPACE);
862                tempBuffer.append(AUTHMETHOD).append(EQ).append(QUOTE).append(
863                        value).append(QUOTE);
864            }
865        }
866        if (tempBuffer.length() != 0) {
867            if (bindRule.length() > 0) {
868                bindRule.append(SPACE).append(AND).append(SPACE);
869            }
870            bindRule.append(OPENPARENTH).append(tempBuffer)
871                    .append(CLOSEPARENTH);
872        }
873
874        StringBuffer ipBuffer = new StringBuffer();
875        collection = getClientIP();
876        if (collection != null && !collection.isEmpty()) {
877            iter = collection.iterator();
878            if (iter.hasNext()) {
879                value = (String) iter.next();
880                ipBuffer.append(IP).append(EQ).append(QUOTE).append(value)
881                        .append(QUOTE);
882            }
883            while (iter.hasNext()) {
884                value = (String) iter.next();
885                ipBuffer.append(SPACE).append(OR).append(SPACE);
886                ipBuffer.append(IP).append(EQ).append(QUOTE).append(value)
887                        .append(QUOTE);
888            }
889        }
890
891        tempBuffer.setLength(0);
892        collection = getClientHostNames();
893        if (collection != null && !collection.isEmpty()) {
894            iter = collection.iterator();
895            if (iter.hasNext()) {
896                value = (String) iter.next();
897                tempBuffer.append(DNS).append(EQ).append(QUOTE).append(value)
898                        .append(QUOTE);
899            }
900            while (iter.hasNext()) {
901                value = (String) iter.next();
902                tempBuffer.append(SPACE).append(OR).append(SPACE);
903                tempBuffer.append(DNS).append(EQ).append(QUOTE).append(value)
904                        .append(QUOTE);
905            }
906        }
907        if (ipBuffer.length() != 0) {
908            ipBuffer.append(SPACE).append(OR).append(SPACE).append(tempBuffer);
909        } else {
910            ipBuffer.append(tempBuffer);
911        }
912
913        if (ipBuffer.length() != 0) {
914            if (bindRule.length() > 0) {
915                bindRule.append(NEWLINE).append(SPACE).append(AND);
916            }
917            bindRule.append(SPACE).append(OPENPARENTH).append(ipBuffer).append(
918                    CLOSEPARENTH);
919        }
920
921        tempBuffer.setLength(0);
922        collection = getDaysOfWeek();
923        if (collection != null && !collection.isEmpty()) {
924            iter = collection.iterator();
925            if (iter.hasNext()) {
926                value = (String) iter.next();
927                tempBuffer.append(DAYOFWEEK).append(EQ).append(QUOTE).append(
928                        value);
929            }
930            while (iter.hasNext()) {
931                value = (String) iter.next();
932                tempBuffer.append(COMMA).append(SPACE).append(value);
933            }
934            tempBuffer.append(QUOTE).append(SPACE);
935        }
936        if (tempBuffer.length() != 0) {
937            if (bindRule.length() > 0) {
938                bindRule.append(NEWLINE).append(SPACE).append(AND)
939                        .append(SPACE);
940            }
941            bindRule.append(OPENPARENTH).append(tempBuffer)
942                    .append(CLOSEPARENTH);
943        }
944
945        tempBuffer.setLength(0);
946        collection = getTimesOfDay();
947        if (collection != null && !collection.isEmpty()) {
948            iter = collection.iterator();
949            if (iter.hasNext()) {
950                value = (String) iter.next();
951                tempBuffer.append(TIMEOFDAY).append(GE).append(QUOTE).append(
952                        value).append(QUOTE);
953            }
954            if (iter.hasNext()) {
955                value = (String) iter.next();
956                tempBuffer.append(SPACE).append(AND).append(SPACE);
957                tempBuffer.append(TIMEOFDAY).append(LE).append(QUOTE).append(
958                        value).append(QUOTE);
959            }
960            while (iter.hasNext()) {
961                value = (String) iter.next();
962                tempBuffer.append(SPACE).append(OR).append(SPACE);
963                tempBuffer.append(TIMEOFDAY).append(GE).append(QUOTE).append(
964                        value).append(QUOTE);
965                if (iter.hasNext()) {
966                    value = (String) iter.next();
967                    tempBuffer.append(SPACE).append(AND).append(SPACE);
968                    tempBuffer.append(TIMEOFDAY).append(LE).append(QUOTE)
969                            .append(value).append(QUOTE);
970                }
971            }
972        }
973        if (tempBuffer.length() != 0) {
974            if (bindRule.length() > 0) {
975                bindRule.append(NEWLINE).append(SPACE).append(AND)
976                        .append(SPACE);
977            }
978            bindRule.append(OPENPARENTH).append(tempBuffer)
979                    .append(CLOSEPARENTH);
980        }
981
982        if (bindRule.length() != 0) {
983            aci.append(bindRule);
984        }
985        aci.append(SEMICOLON).append(SPACE).append(CLOSEPARENTH);
986        return aci.toString().replace('\n', ' ');
987    }
988
989    /**
990     * Converts aci text to ACI
991     * 
992     * @param aciText
993     *            value of aci attribute, typically read from directoy server
994     * @return the converted ACI
995     * @supported.api
996     */
997    public static ACI valueOf(String aciText) throws ACIParseException {
998        return ACIParser.parseACI(aciText);
999    }
1000
1001    /**
1002     * Set the user DN attributes
1003     * @supported.api
1004     */
1005    public void setUserDNAttrs(Collection values) {
1006        _userDNAttrs = values;
1007    }
1008
1009    /**
1010     * Get the DN attributes.
1011     * @supported.api
1012     */
1013    public Collection getUserDNAttrs() {
1014        return _userDNAttrs;
1015    }
1016
1017    /**
1018     * Set the group DN attributes.
1019     * @supported.api
1020     */
1021    public void setGroupDNAttrs(Collection values) {
1022        _groupDNAttrs = values;
1023    }
1024
1025    /**
1026     * Get the group DN attributes.
1027     * @supported.api
1028     */
1029    Collection getGroupDNAttrs() {
1030        return _groupDNAttrs;
1031    }
1032
1033    /**
1034     * Set the user attributes.
1035     * @supported.api
1036     */
1037    public void setUserAttrs(Collection values) {
1038        _userAttrs = values;
1039    }
1040
1041    /**
1042     * Get the user Attributes.
1043     * @supported.api
1044     */
1045    public Collection getUserAttrs() {
1046        return _userAttrs;
1047    }
1048
1049    /**
1050     * Set the ACI text.
1051     * @supported.api
1052     */
1053    public void setACIText(String aciText) {
1054        _aciText = aciText;
1055    }
1056
1057    /**
1058     * Get the ACI text.
1059     * @supported.api
1060     */
1061    public String getACIText() {
1062        return _aciText;
1063    }
1064
1065    /**
1066     * Set the Access Control Rule.
1067     * @supported.api
1068     */
1069    public void setACR(ACR acr) {
1070        setVersion(acr.getVersion());
1071        setName(acr.getName());
1072        setPermissions(acr.getPermissions());
1073        BindRule br = acr.getBindRule();
1074        setUsers(br.getUsers());
1075        setGroups(br.getGroups());
1076        setRoles(br.getRoles());
1077        setUserDNAttrs(br.getUserDNAttrs());
1078        setGroupDNAttrs(br.getGroupDNAttrs());
1079        setUserAttrs(br.getUserAttrs());
1080        setAuthMethods(br.getAuthMethods());
1081        setClientIP(br.getClientIP());
1082        setClientHostNames(br.getClientHostNames());
1083        setDaysOfWeek(br.getDaysOfWeek());
1084        setTimesOfDay(br.getTimesOfDay());
1085    }
1086
1087    /**
1088     * Set the version number of the ACI.
1089     * @supported.api
1090     */
1091    public void setVersion(String version) {
1092        _version = version;
1093    }
1094
1095    /**
1096     * Get the version number.
1097     * @supported.api
1098     */
1099    public String getVersion() {
1100        return _version;
1101    }
1102
1103    private String _target;
1104
1105    private String _targetFilter;
1106
1107    private String _targetAttrFilters;
1108
1109    private QualifiedCollection _targetAttributes;
1110
1111    private String _name = "Unnamed";
1112
1113    private String _version = "3.0";
1114
1115    private QualifiedCollection _permissions;
1116
1117    private Collection _users;
1118
1119    private Collection _groups;
1120
1121    private Collection _roles;
1122
1123    private Collection _clientIP;
1124
1125    private Collection _clientHostNames;
1126
1127    private Collection _timesOfDay;
1128
1129    private Collection _daysOfWeek;
1130
1131    private Collection _authMethods;
1132
1133    private Collection _userDNAttrs;
1134
1135    private Collection _groupDNAttrs;
1136
1137    private Collection _userAttrs;
1138
1139    private String _aciText = "";
1140}
1141
1142/**
1143 * Support class with utility methods used to parse the value of aci attibute
1144 * read from the directory server to ACI object
1145 */
1146class ACIParser {
1147
1148    static ACI parseACI(String aciText) throws ACIParseException {
1149        ACI aci = new ACI();
1150        aci.setACIText(aciText);
1151        if (aciText == null) {
1152            throw new ACIParseException("Malformed aci");
1153        } else {
1154            aciText = aciText.trim();
1155            int length = aciText.length();
1156            if (aciText.length() == 0) {
1157                throw new ACIParseException("Malformed aci:aci is blank");
1158            } else if ((aciText.charAt(0) != '(')
1159                    || (aciText.charAt(length - 1) != ')')) {
1160                throw new ACIParseException(
1161                        "Malformed aci: aci not enclosed in parenthesis");
1162            } else {
1163                ArrayList topLevelSubExpressions = getSubExpressions(aciText);
1164                if (topLevelSubExpressions.size() > 5) {
1165                    throw new ACIParseException(
1166                            "Malformed aci: more than 5 toplevel " +
1167                            "subexpressions");
1168                }
1169                for (int i = 0; i < topLevelSubExpressions.size(); i++) {
1170                    String subExpression = (String) topLevelSubExpressions
1171                            .get(i);
1172                    if (subExpression.length() < 6) {
1173                        throw new ACIParseException(
1174                                "Malformed aci:too short to be valid");
1175                    }
1176                    String lcSubExpression = subExpression.substring(1)
1177                            .toLowerCase().trim();
1178                    if (lcSubExpression.indexOf(ACI.TARGET) == 0) {
1179                        ACITargetExpression aciTargetExpression = 
1180                            ACITargetExpression.valueOf(subExpression);
1181                        // System.out.println(aciTargetExpression);
1182                        if (aciTargetExpression.getKeyword().equals(ACI.TARGET))
1183                        {
1184                            if (aciTargetExpression.getOperator()
1185                                    .equals(ACI.EQ)) {
1186                                aci.setTarget(aciTargetExpression.getValue());
1187                            } else {
1188                                throw new ACIParseException(
1189                                        "Unsupported operator for : "
1190                                                + ACI.TARGET);
1191                            }
1192                        } else if (aciTargetExpression.getKeyword().equals(
1193                                ACI.TARGETFILTER)) {
1194                            if (aciTargetExpression.getOperator()
1195                                    .equals(ACI.EQ)) {
1196                                aci.setTargetFilter(aciTargetExpression
1197                                        .getValue());
1198                            } else {
1199                                throw new ACIParseException(
1200                                        "Unsupported operator for : "
1201                                                + ACI.TARGETFILTER);
1202                            }
1203                        } else if (aciTargetExpression.getKeyword().equals(
1204                                ACI.TARGETATTRFILTERS)) {
1205                            if (aciTargetExpression.getOperator()
1206                                    .equals(ACI.EQ)) {
1207                                aci.setTargetAttrFilters(aciTargetExpression
1208                                        .getValue());
1209                            } else {
1210                                throw new ACIParseException(
1211                                        "Unsupported operator for : "
1212                                                + ACI.TARGETATTRFILTERS);
1213                            }
1214                        } else if (aciTargetExpression.getKeyword().equals(
1215                                ACI.TARGETATTR)) {
1216                            boolean exclusive = false;
1217                            QualifiedCollection qc = null;
1218                            Collection collection = null;
1219                            if (aciTargetExpression.getOperator()
1220                                    .equals(ACI.EQ)) {
1221                                exclusive = false;
1222                                collection = getTokens(aciTargetExpression
1223                                        .getValue(), ACI.OR_PIPE);
1224                                qc = new QualifiedCollection(collection,
1225                                        exclusive);
1226                                aci.setTargetAttributes(qc);
1227                            } else if (aciTargetExpression.getOperator()
1228                                    .equals(ACI.NE)) {
1229                                exclusive = true;
1230                                collection = getTokens(aciTargetExpression
1231                                        .getValue(), ACI.OR_PIPE);
1232                                qc = new QualifiedCollection(collection,
1233                                        exclusive);
1234                                aci.setTargetAttributes(qc);
1235                            } else {
1236                                throw new ACIParseException(
1237                                        "Unsupported operator for : "
1238                                                + ACI.TARGETATTR);
1239                            } // check for targetattr complete
1240                        } else {
1241                            throw new ACIParseException(
1242                                    "Unsupported keyword : "
1243                                            + aciTargetExpression.getKeyword());
1244                        }// check for target* complete
1245                    } else if (lcSubExpression.indexOf(ACI.VERSION) == 0) {
1246                        ACR acr = ACRParser.parse(subExpression);
1247                        aci.setACR(acr);
1248                    } else {
1249                        throw new ACIParseException(
1250                                "Malformed aci:invalid toplevel subexpression");
1251                    }
1252                }
1253            }
1254        }
1255        if (aci.getPermissions() == null) {
1256            throw new ACIParseException("permissions not defined");
1257        }
1258        return aci;
1259    }
1260
1261    static ArrayList getSubExpressions(String text) throws ACIParseException {
1262        ArrayList subExpressions = new ArrayList();
1263        text = text.trim();
1264        int length = text.length();
1265        if (length <= 0) {
1266            return subExpressions;
1267        } else if ((text.charAt(0) != '(') || (text.charAt(length - 1) != ')'))
1268        {
1269            throw new ACIParseException("Unmatched parenthesis");
1270        }
1271        boolean quoted = false;
1272        int parenthCount = 0;
1273        int i = 0;
1274        for (; i < length; i++) {
1275            if (text.charAt(i) == '\"') {
1276                quoted = !quoted;
1277            } else if (!quoted && (text.charAt(i) == '(')) {
1278                parenthCount++;
1279            } else if (!quoted && (text.charAt(i) == ')')) {
1280                parenthCount--;
1281            }
1282            if (parenthCount == 0)
1283                break;
1284        }
1285        if (parenthCount != 0) {
1286            throw new ACIParseException("Unmatched \" or parenthesis ");
1287        }
1288        subExpressions.add(text.substring(0, i + 1));
1289        if ((i + 1) < length) {
1290            subExpressions.addAll(getSubExpressions(text.substring(i + 1)));
1291        }
1292        return subExpressions;
1293    }
1294
1295    static Collection getTokens(String text, String separator) {
1296        int index = 0;
1297        int startIndex = 0;
1298        int tokenSize = separator.length();
1299        ArrayList tokens = new ArrayList();
1300        while ((index = text.indexOf(separator, startIndex)) != -1) {
1301            tokens.add(text.substring(startIndex, index).trim());
1302            startIndex = index + tokenSize;
1303        }
1304        tokens.add(text.substring(startIndex));
1305        return tokens;
1306    }
1307}
1308
1309/**
1310 * Class to represent the expressions for target, targetattr and targetfilter
1311 */
1312class ACITargetExpression {
1313    private String _keyword;
1314
1315    private String _operator;
1316
1317    private String _value;
1318
1319    ACITargetExpression(String keyword, String operator, String value) {
1320        _keyword = keyword.toLowerCase();
1321        _operator = operator;
1322        _value = value;
1323    }
1324
1325    String getKeyword() {
1326        return _keyword;
1327    }
1328
1329    String getOperator() {
1330        return _operator;
1331    }
1332
1333    String getValue() {
1334        return _value;
1335    }
1336
1337    static ACITargetExpression valueOf(String text) throws ACIParseException {
1338        String keyword = null;
1339        String operator = null;
1340        String value = null;
1341        int opIndex = text.indexOf(ACI.EQ);
1342        if (opIndex <= 0) {
1343            throw new ACIParseException("Malformed aci");
1344        } else if (text.charAt(opIndex - 1) == '!') {
1345            opIndex--;
1346            operator = ACI.NE;
1347        } else {
1348            operator = ACI.EQ;
1349        }
1350        keyword = text.substring(1, opIndex).trim();
1351        value = text.substring(opIndex + operator.length(), text.length() - 1)
1352                .trim();
1353        value = trimSurroundingQuotes(value);
1354        return new ACITargetExpression(keyword, operator, value);
1355    }
1356
1357    /**
1358     * Returns the string representation of ACITargetExpression
1359     *
1360     * @supported.api
1361     */
1362    public String toString() {
1363        StringBuilder sb = new StringBuilder();
1364        sb.append(_keyword).append(":").append(_operator).append(":").append(_value);
1365        return sb.toString();
1366    }
1367
1368    static String trimSurroundingQuotes(String str) {
1369        if (str != null && str.length() > 1 && (str.charAt(0) == '"')
1370                && (str.charAt(str.length() - 1) == '"')) {
1371            str = str.substring(1, str.length() - 1);
1372        }
1373        return str;
1374    }
1375}
1376
1377/**
1378 * Class with utility methods to parse version, aci name and acr of the aci
1379 */
1380class ACRParser {
1381    static ACR parse(String text) throws ACIParseException {
1382        // get the version
1383        ACR acr = new ACR();
1384        if (text.length() < 6) {
1385            throw new ACIParseException("Malformed aci");
1386        }
1387        text = text.substring(1, text.length() - 1).trim();
1388        if (text.charAt(text.length() - 1) != ';') {
1389            throw new ACIParseException("Malformed aci");
1390        }
1391
1392        String lcText = text.toLowerCase();
1393        int colonIndex = 0;
1394        if (lcText.indexOf(ACI.VERSION) == 0) {
1395            text = text.substring((ACI.VERSION).length()).trim();
1396            colonIndex = text.indexOf(ACI.SEMICOLON);
1397            if ((colonIndex < 0) || (colonIndex == (text.length() - 1))) {
1398                throw new ACIParseException("Malformed aci");
1399            }
1400            String version = text.substring(0, colonIndex).trim();
1401            acr.setVersion(version);
1402            text = text.substring(colonIndex + 1);
1403        } else {
1404            throw new ACIParseException("Malformed aci");
1405        }
1406
1407        text = text.trim();
1408        lcText = text.toLowerCase();
1409        if ((lcText.indexOf(ACI.ACL) == 0) || (lcText.indexOf(ACI.ACI) == 0)) {
1410            text = text.substring((ACI.ACL).length()).trim();
1411            colonIndex = text.indexOf(";");
1412            if ((colonIndex < 0) || (colonIndex == (text.length() - 1))) {
1413                throw new ACIParseException("Malformed aci");
1414            }
1415            String aclName = text.substring(0, colonIndex).trim();
1416            int aclNameLength = aclName.length();
1417            if ((aclNameLength < 3) || aclName.charAt(0) != '"'
1418                    || aclName.charAt(aclNameLength - 1) != '"') {
1419                throw new ACIParseException("Malformed aci");
1420            }
1421            aclName = aclName.substring(1, aclNameLength - 1);
1422            acr.setName(aclName);
1423            text = text.substring(colonIndex + 1);
1424        } else {
1425            throw new ACIParseException("Malformed aci");
1426        }
1427
1428        boolean allowed = false;
1429        boolean denied = false;
1430        String permissionMode = null;
1431        text = text.trim();
1432        lcText = text.toLowerCase();
1433        if (lcText.indexOf(ACI.ALLOW) == 0) {
1434            allowed = true;
1435            permissionMode = ACI.ALLOW;
1436        } else if (lcText.indexOf(ACI.DENY) == 0) {
1437            denied = true;
1438            permissionMode = ACI.DENY;
1439        }
1440
1441        if (allowed || denied) {
1442            colonIndex = text.indexOf(ACI.SEMICOLON);
1443            if ((colonIndex < 0) || (colonIndex != (text.length() - 1))) {
1444                throw new ACIParseException("Malformed aci");
1445            }
1446            text = text.substring(0, colonIndex);
1447            text = text.substring(permissionMode.length()).trim();
1448            int parenthIndex = text.indexOf(ACI.CLOSEPARENTH);
1449            String permissionExpression = text.substring(0, parenthIndex + 1);
1450            text = text.substring(parenthIndex + 1).trim();
1451            int peLength = permissionExpression.length();
1452            if ((peLength < 3) || (permissionExpression.charAt(0) != '(')
1453                    || (permissionExpression.charAt(peLength - 1) != ')')) {
1454                throw new ACIParseException(
1455                        "Malformed aci-invlaid permission expression : "
1456                                + permissionExpression);
1457            }
1458            permissionExpression = permissionExpression.substring(1,
1459                    peLength - 1);
1460            Collection permissions = ACIParser.getTokens(permissionExpression,
1461                    ACI.COMMA);
1462            QualifiedCollection qc = new QualifiedCollection(permissions,
1463                    denied);
1464            acr.setPermissions(qc);
1465        } else {
1466            throw new ACIParseException("Malformed aci");
1467        }
1468
1469        BindRuleTokenizer tokenizer = new BindRuleTokenizer(text);
1470        BindRuleBuilder brBuilder = new BindRuleBuilder();
1471        String token = null;
1472        while ((token = tokenizer.nextToken()) != null) {
1473            // System.out.println( "token : " + token);
1474            brBuilder.addToken(token);
1475        }
1476        acr.setBindRule(brBuilder.getBindRule());
1477        return acr;
1478    }
1479
1480}
1481
1482/**
1483 * Class to represent the version, aci name and acr of aci
1484 */
1485class ACR {
1486    String _version;
1487
1488    String _name;
1489
1490    QualifiedCollection _permissions;
1491
1492    BindRule _bindRule;
1493
1494    ACR() {
1495    }
1496
1497    void setVersion(String version) {
1498        _version = version;
1499    }
1500
1501    String getVersion() {
1502        return _version;
1503    }
1504
1505    void setName(String name) {
1506        _name = name;
1507    }
1508
1509    String getName() {
1510        return _name;
1511    }
1512
1513    void setPermissions(QualifiedCollection permissions) {
1514        _permissions = permissions;
1515    }
1516
1517    QualifiedCollection getPermissions() {
1518        return _permissions;
1519    }
1520
1521    void setBindRule(BindRule bindRule) {
1522        _bindRule = bindRule;
1523    }
1524
1525    BindRule getBindRule() {
1526        return _bindRule;
1527    }
1528}
1529
1530class BindRule {
1531
1532    Collection _users;
1533
1534    Collection _groups;
1535
1536    Collection _roles;
1537
1538    Collection _authMethods;
1539
1540    Collection _clientIP;
1541
1542    Collection _clientHostNames;
1543
1544    Collection _timesOfDay;
1545
1546    String _todOp;
1547
1548    Collection _daysOfWeek;
1549
1550    String _previousTodOperator;
1551
1552    Collection _userDNAttrs;
1553
1554    Collection _groupDNAttrs;
1555
1556    Collection _userAttrs;
1557
1558    BindRule() {
1559    }
1560
1561    void addUsers(String value) throws ACIParseException {
1562        if (_users == null) {
1563            _users = new ArrayList();
1564        }
1565        Iterator c = ACIParser.getTokens(value, ACI.OR_PIPE).iterator();
1566        while (c.hasNext()) {
1567            String str = ((String) c.next()).trim();
1568            if (str.indexOf(ACI.LDAP_PREFIX) == 0) {
1569                _users.add(str.substring((ACI.LDAP_PREFIX).length()));
1570            } else if (str.toLowerCase().indexOf(ACI.LDAP_PREFIX) == 0) {
1571                _users.add(str.substring((ACI.LDAP_PREFIX).length()));
1572            } else {
1573                throw new ACIParseException("Malformed userDN : " + str);
1574            }
1575        }
1576    }
1577
1578    Collection getUsers() {
1579        return _users;
1580    }
1581
1582    void addGroups(String value) throws ACIParseException {
1583        if (_groups == null) {
1584            _groups = new ArrayList();
1585        }
1586        Iterator c = ACIParser.getTokens(value, ACI.OR_PIPE).iterator();
1587        while (c.hasNext()) {
1588            String str = (String) c.next();
1589            if (str.indexOf(ACI.LDAP_PREFIX) == 0) {
1590                _groups.add(str.substring((ACI.LDAP_PREFIX).length()));
1591            } else if (str.toLowerCase().indexOf(ACI.LDAP_PREFIX) == 0) {
1592                _groups.add(str.substring((ACI.LDAP_PREFIX).length()));
1593            } else {
1594                throw new ACIParseException("Malformed groupDN : " + value);
1595            }
1596        }
1597    }
1598
1599    Collection getGroups() {
1600        return _groups;
1601    }
1602
1603    void addRoles(String value) throws ACIParseException {
1604        if (_roles == null) {
1605            _roles = new ArrayList();
1606        }
1607        Iterator c = ACIParser.getTokens(value, ACI.OR_PIPE).iterator();
1608        while (c.hasNext()) {
1609            String str = (String) c.next();
1610            if (str.indexOf(ACI.LDAP_PREFIX) == 0) {
1611                _roles.add(str.substring((ACI.LDAP_PREFIX).length()));
1612            } else if (str.toLowerCase().indexOf(ACI.LDAP_PREFIX) == 0) {
1613                _roles.add(str.substring((ACI.LDAP_PREFIX).length()));
1614            } else {
1615                throw new ACIParseException("Malformed roleDN : " + value);
1616            }
1617        }
1618    }
1619
1620    Collection getRoles() {
1621        return _roles;
1622    }
1623
1624    void addUserDNAttr(String value) {
1625        if (_userDNAttrs == null) {
1626            _userDNAttrs = new ArrayList();
1627        }
1628        _userDNAttrs.add(value);
1629    }
1630
1631    Collection getUserDNAttrs() {
1632        return _userDNAttrs;
1633    }
1634
1635    void addGroupDNAttr(String value) {
1636        if (_groupDNAttrs == null) {
1637            _groupDNAttrs = new ArrayList();
1638        }
1639        _groupDNAttrs.add(value);
1640    }
1641
1642    Collection getGroupDNAttrs() {
1643        return _groupDNAttrs;
1644    }
1645
1646    void addAuthMethod(String value) {
1647        if (_authMethods == null) {
1648            _authMethods = new ArrayList();
1649        }
1650        _authMethods.add(value);
1651    }
1652
1653    Collection getAuthMethods() {
1654        return _authMethods;
1655    }
1656
1657    void addClientIP(String value) {
1658        if (_clientIP == null) {
1659            _clientIP = new ArrayList();
1660        }
1661        _clientIP.add(value);
1662    }
1663
1664    Collection getClientIP() {
1665        return _clientIP;
1666    }
1667
1668    void addClientHostName(String value) {
1669        if (_clientHostNames == null) {
1670            _clientHostNames = new ArrayList();
1671        }
1672        _clientHostNames.add(value);
1673    }
1674
1675    Collection getClientHostNames() {
1676        return _clientHostNames;
1677    }
1678
1679    void addTimeOfDay(String value, String operator) throws ACIParseException {
1680        if (_timesOfDay == null) {
1681            _timesOfDay = new ArrayList();
1682        }
1683        if (!operator.equals(ACI.GE) && !operator.equals(ACI.LE)) {
1684            throw new ACIParseException("Illegal operator for timeofday : "
1685                    + operator);
1686        }
1687        if ((_previousTodOperator == null) && (!operator.equals(ACI.GE))) {
1688            throw new ACIParseException(
1689                    "Illegal first operator for timeofday : " + operator);
1690        } else if (operator.equals(_previousTodOperator)) {
1691            throw new ACIParseException(
1692                    "Illegal operator sequence for timeofday : " + operator);
1693        }
1694        _timesOfDay.add(value);
1695        _previousTodOperator = operator;
1696    }
1697
1698    Collection getTimesOfDay() {
1699        return _timesOfDay;
1700    }
1701
1702    void addDaysOfWeek(String value) {
1703        if (_daysOfWeek == null) {
1704            _daysOfWeek = new ArrayList();
1705        }
1706        _daysOfWeek.addAll(ACIParser.getTokens(value, ACI.COMMA));
1707    }
1708
1709    Collection getDaysOfWeek() {
1710        return _daysOfWeek;
1711    }
1712
1713    void addUserAttr(String value) {
1714        if (_userAttrs == null) {
1715            _userAttrs = new ArrayList();
1716        }
1717        _userAttrs.add(value);
1718    }
1719
1720    Collection getUserAttrs() {
1721        return _userAttrs;
1722    }
1723
1724}
1725
1726class BindRuleBuilder {
1727    String _previousToken;
1728
1729    String _previousTokenType = "";
1730
1731    String _previousKeyword;
1732
1733    String _previousKeywordSet;
1734
1735    String _previousExpressionConnector;
1736
1737    String _token;
1738
1739    String _tokenType; // keyword, opearotr, value, expressionconnector,
1740                        // openparenth, closeparenth
1741
1742    String _keyword;
1743
1744    String _keywordSet;
1745
1746    ArrayList _doneKeywordSets = new ArrayList();
1747
1748    String _operator;
1749
1750    String _value;
1751
1752    String _expressionConnector;
1753
1754    int _parenthCount;
1755
1756    int _keywordCount;
1757
1758    int _previousKeywordCount;
1759
1760    BindRule br = new BindRule();
1761
1762    void addToken(String token) throws ACIParseException {
1763        _tokenType = getTokenType(token);
1764        if (_previousTokenType.equals(ACI.KEYWORD)
1765                && !_tokenType.equals(ACI.OPERATOR)) {
1766            throw new ACIParseException("keyword not followed by operator : "
1767                    + _previousToken);
1768        }
1769        if (_previousTokenType.equals(ACI.OPERATOR)
1770                && !_tokenType.equals(ACI.VALUE)) {
1771            throw new ACIParseException("operator not followed by value");
1772        }
1773        if (_previousTokenType.equals(ACI.VALUE)
1774                && !_tokenType.equals(ACI.EXPRESSIONCONNECTOR)
1775                && !_tokenType.equals(ACI.OPENPARENTH)
1776                && !_tokenType.equals(ACI.CLOSEPARENTH)) {
1777            throw new ACIParseException("value not followed by connector : "
1778                    + _previousToken);
1779        }
1780        if (_previousTokenType.equals(ACI.EXPRESSIONCONNECTOR)
1781                && !_tokenType.equals(ACI.KEYWORD)
1782                && !_tokenType.equals(ACI.OPENPARENTH)) {
1783            throw new ACIParseException(
1784                    "expressionconnector not followed by keyword : " + token);
1785        }
1786
1787        if (_tokenType.equals(ACI.OPENPARENTH)) {
1788            _parenthCount++;
1789        } else if (_tokenType.equals(ACI.CLOSEPARENTH)) {
1790            _parenthCount--;
1791        } else if (_tokenType.equals(ACI.KEYWORD)) {
1792            // if ( _keywordCount == 0 ) {
1793            // _keywordCount = 1;
1794            // }
1795            _keyword = token.toLowerCase();
1796            _keywordSet = getKeywordSet(token);
1797            if (_doneKeywordSets.contains(_keywordSet)) {
1798                throw new ACIParseException(
1799                        "keywords from diffrent sets overlap");
1800            }
1801            if ((_previousKeywordSet != null)
1802                    && !_keywordSet.equals(_previousKeywordSet)) {
1803                _doneKeywordSets.add(_previousKeywordSet);
1804                _keywordCount = 0; // 1 ;
1805                if (!_expressionConnector.equals(ACI.AND)) {
1806                    throw new ACIParseException(
1807                            "sets of of keywords have to be "
1808                                    + " connected  by logical and ");
1809                }
1810            } else {
1811                _keywordCount++;
1812                if ((_keywordCount > 1) && !_keywordSet.equals(ACI.TOD_SET)
1813                        && (!(ACI.OR).equals(_expressionConnector))) { 
1814                    // || (_parenthCount < 1) )) {
1815                    throw new ACIParseException(
1816                            "keywords from the same set has to "
1817                                    + " be connected  by logical OR : " 
1818                                    + token);
1819                    // + " and enclosed in parenthesis ");
1820                }
1821            }
1822            _previousKeyword = _keyword;
1823            _previousKeywordSet = _keywordSet;
1824            _previousKeywordCount = _keywordCount;
1825        } else if (_tokenType.equals(ACI.OPERATOR)) {
1826            _operator = token.toLowerCase();
1827        } else if (_tokenType.equals(ACI.VALUE)) {
1828            _value = token.substring(1, token.length() - 1);
1829            if (_keyword == null) {
1830                throw new ACIParseException("keyword is null");
1831            }
1832            addParameter(_keyword, _operator, _value);
1833            // _operator = null;
1834            _value = null;
1835        } else if (_tokenType.equals(ACI.EXPRESSIONCONNECTOR)) {
1836            _expressionConnector = token.toLowerCase();
1837            if (_expressionConnector.equals(ACI.AND)
1838                    && !(ACI.TIMEOFDAY).equals(_keyword)) {
1839                if (_parenthCount != 0) {
1840                    throw new ACIParseException(
1841                            "Can not enclose keywords from "
1842                                  + " different sets in the same parenthesis");
1843                }
1844                if ((_previousKeywordCount > 1)
1845                        && !(ACI.CLOSEPARENTH).equals(_previousTokenType)) {
1846                    throw new ACIParseException("preceding set of expressions "
1847                            + " not enclosed in parenthesis");
1848                }
1849            }
1850        } else if (_tokenType.equals(ACI.OR_PIPE)) {
1851        } else {
1852            throw new ACIParseException("Unknown token type for : " + token);
1853        }
1854        _previousTokenType = _tokenType;
1855    }
1856
1857    String getKeywordSet(String keyword) throws ACIParseException {
1858        String keywordSet = null;
1859        if (keyword.equals(ACI.USERDN) || keyword.equals(ACI.USERDNATTR)
1860                || keyword.equals(ACI.GROUPDN)
1861                || keyword.equals(ACI.GROUPDNATTR)
1862                || keyword.equals(ACI.ROLEDN) || keyword.equals(ACI.USERATTR)) {
1863            keywordSet = ACI.PRINCIPAL_SET;
1864        } else if (keyword.equals(ACI.IP) || keyword.equals(ACI.DNS)) {
1865            keywordSet = ACI.IP_SET;
1866        } else if (keyword.equals(ACI.AUTHMETHOD)) {
1867            keywordSet = ACI.AUTHMETHOD_SET;
1868        } else if (keyword.equals(ACI.TIMEOFDAY)) {
1869            keywordSet = ACI.TOD_SET;
1870        } else if (keyword.equals(ACI.DAYOFWEEK)) {
1871            keywordSet = ACI.DOW_SET;
1872        } else {
1873            throw new ACIParseException("can not determine keyword set for : "
1874                    + keyword);
1875        }
1876        return keywordSet;
1877    }
1878
1879    String getTokenType(String token) throws ACIParseException {
1880        token = token.toLowerCase();
1881        String tokenType = null;
1882        if ((token.charAt(0) == '"')
1883                && (token.charAt(token.length() - 1) == '"')) {
1884            tokenType = ACI.VALUE;
1885        } else if (token.equals(ACI.USERDN) || token.equals(ACI.USERDNATTR)
1886                || token.equals(ACI.GROUPDN) || token.equals(ACI.GROUPDNATTR)
1887                || token.equals(ACI.ROLEDN) || token.equals(ACI.USERATTR)
1888                || token.equals(ACI.IP) || token.equals(ACI.DNS)
1889                || token.equals(ACI.AUTHMETHOD) || token.equals(ACI.TIMEOFDAY)
1890                || token.equals(ACI.DAYOFWEEK)) {
1891            tokenType = ACI.KEYWORD;
1892        } else if (token.equals(ACI.EQ) || token.equals(ACI.NE)
1893                || token.equals(ACI.LT) || token.equals(ACI.LE)
1894                || token.equals(ACI.GT) || token.equals(ACI.GE)) {
1895            tokenType = ACI.OPERATOR;
1896        } else if (token.equals(ACI.AND) || token.equals(ACI.OR)) {
1897            tokenType = ACI.EXPRESSIONCONNECTOR;
1898        } else if (token.equals(ACI.OPENPARENTH)) {
1899            tokenType = ACI.OPENPARENTH;
1900        } else if (token.equals(ACI.CLOSEPARENTH)) {
1901            tokenType = ACI.CLOSEPARENTH;
1902        } else if (token.equals(ACI.OR_PIPE)) {
1903            tokenType = ACI.OR_PIPE;
1904        } else {
1905            throw new ACIParseException("tokentype unknown for " + token);
1906        }
1907        return tokenType;
1908    }
1909
1910    void addParameter(String keyword, String operator, String value)
1911            throws ACIParseException {
1912        if (!keyword.equals(ACI.TIMEOFDAY) && !operator.equals(ACI.EQ)) {
1913            throw new ACIParseException(" keyword " + keyword
1914                    + " does not allow operator " + operator);
1915        }
1916        if (keyword.equals(ACI.TIMEOFDAY) && operator.equals(ACI.GE)
1917                && _keywordCount > 1 && !(ACI.OR).equals(_expressionConnector))
1918        {
1919            throw new ACIParseException(" illegal operator for timeofday : "
1920                    + operator);
1921        }
1922        if (keyword.equals(ACI.TIMEOFDAY) && operator.equals(ACI.LE)
1923                && !(ACI.AND).equals(_expressionConnector)) {
1924            throw new ACIParseException(" illegal operator for timeofday : "
1925                    + operator);
1926        }
1927        if (keyword.equals(ACI.USERDN)) {
1928            br.addUsers(value);
1929        } else if (keyword.equals(ACI.USERDNATTR)) {
1930            br.addUserDNAttr(value);
1931        } else if (keyword.equals(ACI.GROUPDN)) {
1932            br.addGroups(value);
1933        } else if (keyword.equals(ACI.GROUPDNATTR)) {
1934            br.addGroupDNAttr(value);
1935        } else if (keyword.equals(ACI.ROLEDN)) {
1936            br.addRoles(value);
1937        } else if (keyword.equals(ACI.USERATTR)) {
1938            br.addUserAttr(value);
1939        } else if (keyword.equals(ACI.AUTHMETHOD)) {
1940            br.addAuthMethod(value);
1941        } else if (keyword.equals(ACI.IP)) {
1942            br.addClientIP(value);
1943        } else if (keyword.equals(ACI.DNS)) {
1944            br.addClientHostName(value);
1945        } else if (keyword.equals(ACI.TIMEOFDAY)) {
1946            br.addTimeOfDay(value, operator);
1947        } else if (keyword.equals(ACI.DAYOFWEEK)) {
1948            br.addDaysOfWeek(value);
1949        } else {
1950            throw new ACIParseException("Unknown keyword : " + keyword);
1951        }
1952    }
1953
1954    BindRule getBindRule() {
1955        return br;
1956    }
1957
1958    /**
1959     * Returns the string representation of the Bind rule.
1960     * @supported.api
1961     */
1962    public String toString() {
1963        StringBuilder bindRule = new StringBuilder();
1964        return bindRule.toString();
1965    }
1966
1967}
1968
1969class BindRuleTokenizer {
1970
1971    String _text;
1972
1973    int _textLength;
1974
1975    int _startIndex = 0;
1976
1977    int _currentIndex;
1978
1979    BindRuleTokenizer(String text) {
1980        _text = text;
1981        _textLength = text.length();
1982        _currentIndex = 0;
1983    }
1984
1985    String nextToken() {
1986        StringBuilder token = new StringBuilder();
1987        if (_currentIndex < _textLength) {
1988            for (; _currentIndex < _textLength; _currentIndex++) {
1989                char c = _text.charAt(_currentIndex);
1990                if (c == '\n' || c == '\r' || c == ' ') {
1991                    if (token.length() == 0) {
1992                        continue;
1993                    } else {
1994                        _currentIndex++;
1995                        break;
1996                    }
1997                } else if (c == '"') {
1998                    if (token.length() == 0) {
1999                        token.append(c);
2000                        while (_currentIndex < (_textLength - 1)) {
2001                            _currentIndex++;
2002                            c = _text.charAt(_currentIndex);
2003                            token.append(c);
2004                            if (c == '"') {
2005                                _currentIndex++;
2006                                break;
2007                            }
2008                        }
2009                    }
2010                    break;
2011                } else if (c == '(' || c == ')') {
2012                    if (token.length() == 0) {
2013                        token.append(c);
2014                        _currentIndex++;
2015                    }
2016                    break;
2017                } else if (c == '<' || c == '>' || c == '!') {
2018                    if (token.length() == 0) {
2019                        token.append(c);
2020                        _currentIndex++;
2021                        if (_currentIndex < (_textLength)
2022                                && ((c = _text.charAt(_currentIndex)) == '=')) {
2023                            token.append(c);
2024                            _currentIndex++;
2025                        }
2026                    }
2027                    break;
2028                } else if (c == '=') {
2029                    if (token.length() == 0) {
2030                        token.append(c);
2031                        _currentIndex++;
2032                    }
2033                    break;
2034                } else {
2035                    token.append(c);
2036                }
2037            }
2038        }
2039        return (token.length() != 0) ? token.toString() : null;
2040    }
2041}