001/*
002 * Copyright 2015-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2019 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util.args;
022
023
024
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Collections;
029import java.util.Iterator;
030import java.util.List;
031
032import com.unboundid.ldap.sdk.DN;
033import com.unboundid.util.Debug;
034import com.unboundid.util.NotMutable;
035import com.unboundid.util.StaticUtils;
036import com.unboundid.util.ThreadSafety;
037import com.unboundid.util.ThreadSafetyLevel;
038import com.unboundid.util.Validator;
039
040import static com.unboundid.util.args.ArgsMessages.*;
041
042
043
044/**
045 * This class provides an implementation of an argument value validator that is
046 * expected to be used with string or DN arguments and ensures that all values
047 * for the argument are valid DNs that are within one or more specified
048 * subtrees.
049 */
050@NotMutable()
051@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
052public final class RequireDNInSubtreeArgumentValueValidator
053       extends ArgumentValueValidator
054       implements Serializable
055{
056  /**
057   * The serial version UID for this serializable class.
058   */
059  private static final long serialVersionUID = -4517307608327628921L;
060
061
062
063  // The set of permitted base DNs for values of the associated argument.
064  private final List<DN> baseDNs;
065
066
067
068  /**
069   * Creates a new instance of this argument value validator with the provided
070   * information.
071   *
072   * @param  baseDNs  The set of permitted base DNs for values of the associated
073   *                  argument.  It must not be {@code null} or empty.
074   */
075  public RequireDNInSubtreeArgumentValueValidator(final DN... baseDNs)
076  {
077    this(StaticUtils.toList(baseDNs));
078  }
079
080
081
082  /**
083   * Creates a new instance of this argument value validator with the provided
084   * information.
085   *
086   * @param  baseDNs  The set of permitted base DNs for values of the associated
087   *                  argument.  It must not be {@code null} or empty.
088   */
089  public RequireDNInSubtreeArgumentValueValidator(final Collection<DN> baseDNs)
090  {
091    Validator.ensureNotNull(baseDNs);
092    Validator.ensureFalse(baseDNs.isEmpty());
093
094    this.baseDNs = Collections.unmodifiableList(new ArrayList<>(baseDNs));
095  }
096
097
098
099  /**
100   * Retrieves a list of the permitted base DNs for this argument value
101   * validator.
102   *
103   * @return  A list of the permitted base DNs for this argument value
104   *          validator.
105   */
106  public List<DN> getBaseDNs()
107  {
108    return baseDNs;
109  }
110
111
112
113  /**
114   * {@inheritDoc}
115   */
116  @Override()
117  public void validateArgumentValue(final Argument argument,
118                                    final String valueString)
119         throws ArgumentException
120  {
121    final DN dn;
122    try
123    {
124      dn = new DN(valueString);
125    }
126    catch (final Exception e)
127    {
128      Debug.debugException(e);
129      throw new ArgumentException(
130           ERR_REQUIRE_DN_IN_SUBTREE_VALIDATOR_VALUE_NOT_DN.get(valueString,
131                argument.getIdentifierString()),
132           e);
133    }
134
135
136    if (baseDNs.size() == 1)
137    {
138      if (! dn.isDescendantOf(baseDNs.get(0), true))
139      {
140        throw new ArgumentException(
141             ERR_REQUIRE_DN_IN_SUBTREE_VALIDATOR_VALUE_NOT_IN_SUBTREE.get(
142                  valueString, argument.getIdentifierString(),
143                  String.valueOf(baseDNs.get(0))));
144      }
145    }
146    else
147    {
148      final StringBuilder dnList = new StringBuilder();
149      final Iterator<DN> iterator = baseDNs.iterator();
150      while (iterator.hasNext())
151      {
152        final DN baseDN = iterator.next();
153        if (dn.isDescendantOf(baseDN, true))
154        {
155          return;
156        }
157
158        dnList.append('\'');
159        dnList.append(baseDN);
160        dnList.append('\'');
161
162        if (iterator.hasNext())
163        {
164          dnList.append(", ");
165        }
166      }
167
168      throw new ArgumentException(
169           ERR_REQUIRE_DN_IN_SUBTREE_VALIDATOR_VALUE_NOT_IN_SUBTREES.get(
170                valueString, argument.getIdentifierString(),
171                dnList.toString()));
172    }
173  }
174
175
176
177  /**
178   * Retrieves a string representation of this argument value validator.
179   *
180   * @return  A string representation of this argument value validator.
181   */
182  @Override()
183  public String toString()
184  {
185    final StringBuilder buffer = new StringBuilder();
186    toString(buffer);
187    return buffer.toString();
188  }
189
190
191
192  /**
193   * Appends a string representation of this argument value validator to the
194   * provided buffer.
195   *
196   * @param  buffer  The buffer to which the string representation should be
197   *                 appended.
198   */
199  public void toString(final StringBuilder buffer)
200  {
201    buffer.append("RequireDNInSubtreeArgumentValueValidator(baseDNs={");
202
203    final Iterator<DN> iterator = baseDNs.iterator();
204    while (iterator.hasNext())
205    {
206      buffer.append('\'');
207      buffer.append(iterator.next().toString());
208      buffer.append('\'');
209
210      if (iterator.hasNext())
211      {
212        buffer.append(", ");
213      }
214    }
215
216    buffer.append("})");
217  }
218}