001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    
028    package org.opends.server.authorization.dseecompat;
029    import org.opends.messages.Message;
030    
031    import static org.opends.messages.AccessControlMessages.*;
032    import static org.opends.server.authorization.dseecompat.Aci.*;
033    import java.util.regex.Pattern;
034    import org.opends.server.types.DN;
035    import org.opends.server.types.DirectoryException;
036    import org.opends.server.types.LDAPURL;
037    
038    /**
039     * A class representing an ACI target keyword.
040     */
041    public class Target
042    {
043        /**
044         * Enumeration representing the target operator.
045         */
046        private EnumTargetOperator operator = EnumTargetOperator.EQUALITY;
047    
048        /**
049         * True if the URL contained a DN wild-card pattern.
050         */
051        private boolean isPattern=false;
052    
053        /**
054         * The target DN from the URL or null if it was a wild-card pattern.
055         */
056        private DN urlDN=null;
057    
058        /**
059         * The pattern matcher for a wild-card pattern or null if the URL
060         * contained an ordinary DN.
061         */
062        private PatternDN patternDN =null;
063    
064        /*
065         * TODO Save aciDN parameter and use it in matchesPattern re-write.
066         *
067         * Should the aciDN argument provided to the constructor be stored so that
068         * it can be used in the matchesPattern() method?  The DN should only be
069         * considered a potential match if it is at or below the entry containing
070         * the ACI.
071         *
072         */
073        /**
074         * This constructor parses the target string.
075         * @param operator  An enumeration of the operation of this target.
076         * @param target A string representation of the target.
077         * @param aciDN The dn of the ACI entry used for a descendant check.
078         * @throws AciException If the target string is invalid.
079         */
080        private Target(EnumTargetOperator operator, String target, DN aciDN)
081                throws AciException {
082            this.operator = operator;
083            try {
084              //The NULL_LDAP_URL corresponds to the root DSE.
085              if((!target.equals(NULL_LDAP_URL)) &&
086                 (!Pattern.matches(LDAP_URL, target))) {
087                  Message message =
088                      WARN_ACI_SYNTAX_INVALID_TARGETKEYWORD_EXPRESSION.get(target);
089                  throw new AciException(message);
090              }
091              LDAPURL targetURL =  LDAPURL.decode(target, false);
092              if(targetURL.getRawBaseDN().indexOf("*") != -1) {
093                  this.isPattern=true;
094                  patternDN = PatternDN.decodeSuffix(targetURL.getRawBaseDN());
095              } else {
096                  urlDN=targetURL.getBaseDN();
097                  if(!urlDN.isDescendantOf(aciDN)) {
098                      Message message = WARN_ACI_SYNTAX_TARGET_DN_NOT_DESCENDENTOF.
099                          get(urlDN.toNormalizedString(),
100                              aciDN.toNormalizedString());
101                      throw new AciException(message);
102                  }
103              }
104            }
105            catch (DirectoryException e){
106                Message message =
107                    WARN_ACI_SYNTAX_INVALID_TARGETKEYWORD_EXPRESSION.get(target);
108                throw new AciException(message);
109            }
110        }
111    
112        /**
113         *  Decode an expression string representing a target keyword expression.
114         * @param operator  An enumeration of the operation of this target.
115         * @param expr A string representation of the target.
116         * @param aciDN  The DN of the ACI entry used for a descendant check.
117         * @return  A Target class representing this target.
118         * @throws AciException  If the expression string is invalid.
119         */
120        public static Target decode(EnumTargetOperator operator,
121                                    String expr, DN aciDN)
122                throws AciException {
123            return new Target(operator, expr, aciDN);
124        }
125    
126        /**
127         * Returns the operator of this expression.
128         * @return An enumeration of the operation value.
129         */
130        public EnumTargetOperator getOperator() {
131            return operator;
132        }
133    
134        /**
135         * Returns the URL DN of the expression.
136         * @return A DN of the URL or null if the URL contained a DN pattern.
137         */
138        public DN getDN() {
139            return urlDN;
140        }
141    
142        /**
143         * Returns boolean if a pattern was seen during parsing.
144         * @return  True if the URL contained a DN pattern.
145         */
146        public boolean isPattern() {
147            return isPattern;
148        }
149    
150        /**
151         * This method tries to match a pattern against a DN.
152         * @param dn  The DN to try an match.
153         * @return True if the pattern matches.
154         */
155        public boolean matchesPattern(DN dn) {
156            return patternDN.matchesDN(dn);
157        }
158    }