001/*
002 * Copyright 2009-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2009-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.tasks;
037
038
039
040import java.util.Arrays;
041import java.util.Collections;
042import java.util.Date;
043import java.util.LinkedHashMap;
044import java.util.LinkedList;
045import java.util.List;
046import java.util.Map;
047
048import com.unboundid.ldap.sdk.Attribute;
049import com.unboundid.ldap.sdk.Entry;
050import com.unboundid.ldap.sdk.Filter;
051import com.unboundid.ldap.sdk.LDAPException;
052import com.unboundid.ldap.sdk.SearchScope;
053import com.unboundid.util.Debug;
054import com.unboundid.util.NotMutable;
055import com.unboundid.util.NotNull;
056import com.unboundid.util.Nullable;
057import com.unboundid.util.StaticUtils;
058import com.unboundid.util.ThreadSafety;
059import com.unboundid.util.ThreadSafetyLevel;
060import com.unboundid.util.Validator;
061
062import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
063
064
065
066/**
067 * This class defines a Directory Server task that can be used to perform an
068 * internal search within the server and write the contents to an LDIF file.
069 * <BR>
070 * <BLOCKQUOTE>
071 *   <B>NOTE:</B>  This class, and other classes within the
072 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
073 *   supported for use against Ping Identity, UnboundID, and
074 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
075 *   for proprietary functionality or for external specifications that are not
076 *   considered stable or mature enough to be guaranteed to work in an
077 *   interoperable way with other types of LDAP servers.
078 * </BLOCKQUOTE>
079 * <BR>
080 * The properties that are available for use with this type of task include:
081 * <UL>
082 *   <LI>The base DN to use for the search.  This is required.</LI>
083 *   <LI>The scope to use for the search.  This is required.</LI>
084 *   <LI>The filter to use for the search.  This is required.</LI>
085 *   <LI>The attributes to return.  This is optional and multivalued.</LI>
086 *   <LI>The authorization DN to use for the search.  This is optional.</LI>
087 *   <LI>The path to the output file to use.  This is required.</LI>
088 * </UL>
089 */
090@NotMutable()
091@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
092public final class SearchTask
093       extends Task
094{
095  /**
096   * The fully-qualified name of the Java class that is used for the search
097   * task.
098   */
099  @NotNull static final String SEARCH_TASK_CLASS =
100       "com.unboundid.directory.server.tasks.SearchTask";
101
102
103
104  /**
105   * The name of the attribute used to specify the search base DN.
106   */
107  @NotNull private static final String ATTR_BASE_DN = "ds-task-search-base-dn";
108
109
110
111  /**
112   * The name of the attribute used to specify the search scope.
113   */
114  @NotNull private static final String ATTR_SCOPE = "ds-task-search-scope";
115
116
117
118  /**
119   * The name of the attribute used to specify the search filter.
120   */
121  @NotNull private static final String ATTR_FILTER = "ds-task-search-filter";
122
123
124
125  /**
126   * The name of the attribute used to specify the attribute(s) to return.
127   */
128  @NotNull private static final String ATTR_RETURN_ATTR =
129       "ds-task-search-return-attribute";
130
131
132
133  /**
134   * The name of the attribute used to specify the authorization DN.
135   */
136  @NotNull private static final String ATTR_AUTHZ_DN =
137       "ds-task-search-authz-dn";
138
139
140
141  /**
142   * The name of the attribute used to specify the output file.
143   */
144  @NotNull private static final String ATTR_OUTPUT_FILE =
145       "ds-task-search-output-file";
146
147
148
149  /**
150   * The name of the object class used in search task entries.
151   */
152  @NotNull private static final String OC_SEARCH_TASK = "ds-task-search";
153
154
155
156  /**
157   * The task property that will be used for the base DN.
158   */
159  @NotNull private static final TaskProperty PROPERTY_BASE_DN =
160       new TaskProperty(ATTR_BASE_DN,
161            INFO_SEARCH_TASK_DISPLAY_NAME_BASE_DN.get(),
162            INFO_SEARCH_TASK_DESCRIPTION_BASE_DN.get(), String.class, true,
163            false, false);
164
165
166
167  /**
168   * The allowed values for the scope property.
169   */
170  @NotNull private static final Object[] ALLOWED_SCOPE_VALUES =
171  {
172    "base", "baseobject", "0",
173    "one", "onelevel", "singlelevel", "1",
174    "sub", "subtree", "wholesubtree", "2",
175    "subord", "subordinate", "subordinatesubtree", "3"
176  };
177
178
179
180  /**
181   * The task property that will be used for the scope.
182   */
183  @NotNull private static final TaskProperty PROPERTY_SCOPE =
184       new TaskProperty(ATTR_SCOPE,
185            INFO_SEARCH_TASK_DISPLAY_NAME_SCOPE.get(),
186            INFO_SEARCH_TASK_DESCRIPTION_SCOPE.get(), String.class, true,
187            false, false, ALLOWED_SCOPE_VALUES);
188
189
190
191  /**
192   * The task property that will be used for the filter.
193   */
194  @NotNull private static final TaskProperty PROPERTY_FILTER =
195       new TaskProperty(ATTR_FILTER,
196            INFO_SEARCH_TASK_DISPLAY_NAME_FILTER.get(),
197            INFO_SEARCH_TASK_DESCRIPTION_FILTER.get(), String.class, true,
198            false, false);
199
200
201
202  /**
203   * The task property that will be used for the requested attributes.
204   */
205  @NotNull private static final TaskProperty PROPERTY_REQUESTED_ATTR =
206       new TaskProperty(ATTR_RETURN_ATTR,
207            INFO_SEARCH_TASK_DISPLAY_NAME_RETURN_ATTR.get(),
208            INFO_SEARCH_TASK_DESCRIPTION_RETURN_ATTR.get(), String.class, false,
209            true, false);
210
211
212
213  /**
214   * The task property that will be used for the authorization DN.
215   */
216  @NotNull private static final TaskProperty PROPERTY_AUTHZ_DN =
217       new TaskProperty(ATTR_AUTHZ_DN,
218            INFO_SEARCH_TASK_DISPLAY_NAME_AUTHZ_DN.get(),
219            INFO_SEARCH_TASK_DESCRIPTION_AUTHZ_DN.get(), String.class, false,
220            false, true);
221
222
223
224  /**
225   * The task property that will be used for the output file.
226   */
227  @NotNull private static final TaskProperty PROPERTY_OUTPUT_FILE =
228       new TaskProperty(ATTR_OUTPUT_FILE,
229            INFO_SEARCH_TASK_DISPLAY_NAME_OUTPUT_FILE.get(),
230            INFO_SEARCH_TASK_DESCRIPTION_NAME_OUTPUT_FILE.get(), String.class,
231            true, false, false);
232
233
234
235  /**
236   * The serial version UID for this serializable class.
237   */
238  private static final long serialVersionUID = -1742374271508548328L;
239
240
241
242  // The search filter.
243  @NotNull private final Filter filter;
244
245  // The list of attributes to return.
246  @NotNull private final List<String> attributes;
247
248  // The search scope.
249  @NotNull private final SearchScope scope;
250
251  // The authorization DN.
252  @Nullable private final String authzDN;
253
254  // The search base DN.
255  @NotNull private final String baseDN;
256
257  // The output file path.
258  @NotNull private final String outputFile;
259
260
261
262  /**
263   * Creates a new uninitialized search task instance which should only be used
264   * for obtaining general information about this task, including the task name,
265   * description, and supported properties.  Attempts to use a task created with
266   * this constructor for any other reason will likely fail.
267   */
268  public SearchTask()
269  {
270    filter     = null;
271    attributes = null;
272    scope      = null;
273    authzDN    = null;
274    baseDN     = null;
275    outputFile = null;
276  }
277
278
279
280  /**
281   * Creates a new search task with the provided information.
282   *
283   * @param  taskID      The task ID to use for this task.  If it is
284   *                     {@code null} then a UUID will be generated for use as
285   *                     the task ID.
286   * @param  baseDN      The base DN to use for the search.  It must not be
287   *                     {@code null}.
288   * @param  scope       The scope to use for the search.  It must not be
289   *                     {@code null}.
290   * @param  filter      The filter to use for the search.  It must not be
291   *                     {@code null}.
292   * @param  attributes  The list of attributes to include in matching entries.
293   *                     If it is {@code null} or empty, then all user
294   *                     attributes will be selected.
295   * @param  outputFile  The path to the file (on the server filesystem) to
296   *                     which the results should be written.  It must not be
297   *                     {@code null}.
298   */
299  public SearchTask(@Nullable final String taskID,
300                    @NotNull final String baseDN,
301                    @NotNull final SearchScope scope,
302                    @NotNull final Filter filter,
303                    @Nullable final List<String> attributes,
304                    @NotNull final String outputFile)
305  {
306    this(taskID, baseDN, scope, filter, attributes, outputFile, null, null,
307         null, null, null, null);
308  }
309
310
311
312  /**
313   * Creates a new search task with the provided information.
314   *
315   * @param  taskID      The task ID to use for this task.  If it is
316   *                     {@code null} then a UUID will be generated for use as
317   *                     the task ID.
318   * @param  baseDN      The base DN to use for the search.  It must not be
319   *                     {@code null}.
320   * @param  scope       The scope to use for the search.  It must not be
321   *                     {@code null}.
322   * @param  filter      The filter to use for the search.  It must not be
323   *                     {@code null}.
324   * @param  attributes  The list of attributes to include in matching entries.
325   *                     If it is {@code null} or empty, then all user
326   *                     attributes will be selected.
327   * @param  outputFile  The path to the file (on the server filesystem) to
328   *                     which the results should be written.  It must not be
329   *                     {@code null}.
330   * @param  authzDN     The DN of the user as whom the search should be
331   *                     processed.  If this is {@code null}, then it will be
332   *                     processed as an internal root user.
333   */
334  public SearchTask(@Nullable final String taskID,
335                    @NotNull final String baseDN,
336                    @NotNull final SearchScope scope,
337                    @NotNull final Filter filter,
338                    @Nullable final List<String> attributes,
339                    @NotNull final String outputFile,
340                    @Nullable final String authzDN)
341  {
342    this(taskID, baseDN, scope, filter, attributes, outputFile, authzDN, null,
343         null, null, null, null);
344  }
345
346
347
348  /**
349   * Creates a new search task with the provided information.
350   *
351   * @param  taskID                  The task ID to use for this task.  If it is
352   *                                 {@code null} then a UUID will be generated
353   *                                 for use as the task ID.
354   * @param  baseDN                  The base DN to use for the search.  It must
355   *                                 not be {@code null}.
356   * @param  scope                   The scope to use for the search.  It must
357   *                                 not be {@code null}.
358   * @param  filter                  The filter to use for the search.  It must
359   *                                 not be {@code null}.
360   * @param  attributes              The list of attributes to include in
361   *                                 matching entries.  If it is {@code null} or
362   *                                 empty, then all user attributes will be
363   *                                 selected.
364   * @param  outputFile              The path to the file (on the server
365   *                                 filesystem) to which the results should be
366   *                                 written.  It must not be {@code null}.
367   * @param  authzDN                 The DN of the user as whom the search
368   *                                 should be processed.  If this is
369   *                                 {@code null}, then it will be processed as
370   *                                 an internal root user.
371   * @param  scheduledStartTime      The time that this task should start
372   *                                 running.
373   * @param  dependencyIDs           The list of task IDs that will be required
374   *                                 to complete before this task will be
375   *                                 eligible to start.
376   * @param  failedDependencyAction  Indicates what action should be taken if
377   *                                 any of the dependencies for this task do
378   *                                 not complete successfully.
379   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
380   *                                 that should be notified when this task
381   *                                 completes.
382   * @param  notifyOnError           The list of e-mail addresses of individuals
383   *                                 that should be notified if this task does
384   *                                 not complete successfully.
385   */
386  public SearchTask(@Nullable final String taskID,
387              @NotNull final String baseDN,
388              @NotNull final SearchScope scope,
389              @NotNull final Filter filter,
390              @Nullable final List<String> attributes,
391              @NotNull final String outputFile,
392              @Nullable final String authzDN,
393              @Nullable final Date scheduledStartTime,
394              @Nullable final List<String> dependencyIDs,
395              @Nullable final FailedDependencyAction failedDependencyAction,
396              @Nullable final List<String> notifyOnCompletion,
397              @Nullable final List<String> notifyOnError)
398  {
399    this(taskID, baseDN, scope, filter, attributes, outputFile, authzDN,
400         scheduledStartTime, dependencyIDs, failedDependencyAction, null,
401         notifyOnCompletion, null, notifyOnError, null, null, null);
402  }
403
404
405
406  /**
407   * Creates a new search task with the provided information.
408   *
409   * @param  taskID                  The task ID to use for this task.  If it is
410   *                                 {@code null} then a UUID will be generated
411   *                                 for use as the task ID.
412   * @param  baseDN                  The base DN to use for the search.  It must
413   *                                 not be {@code null}.
414   * @param  scope                   The scope to use for the search.  It must
415   *                                 not be {@code null}.
416   * @param  filter                  The filter to use for the search.  It must
417   *                                 not be {@code null}.
418   * @param  attributes              The list of attributes to include in
419   *                                 matching entries.  If it is {@code null} or
420   *                                 empty, then all user attributes will be
421   *                                 selected.
422   * @param  outputFile              The path to the file (on the server
423   *                                 filesystem) to which the results should be
424   *                                 written.  It must not be {@code null}.
425   * @param  authzDN                 The DN of the user as whom the search
426   *                                 should be processed.  If this is
427   *                                 {@code null}, then it will be processed as
428   *                                 an internal root user.
429   * @param  scheduledStartTime      The time that this task should start
430   *                                 running.
431   * @param  dependencyIDs           The list of task IDs that will be required
432   *                                 to complete before this task will be
433   *                                 eligible to start.
434   * @param  failedDependencyAction  Indicates what action should be taken if
435   *                                 any of the dependencies for this task do
436   *                                 not complete successfully.
437   * @param  notifyOnStart           The list of e-mail addresses of individuals
438   *                                 that should be notified when this task
439   *                                 starts running.
440   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
441   *                                 that should be notified when this task
442   *                                 completes.
443   * @param  notifyOnSuccess         The list of e-mail addresses of individuals
444   *                                 that should be notified if this task
445   *                                 completes successfully.
446   * @param  notifyOnError           The list of e-mail addresses of individuals
447   *                                 that should be notified if this task does
448   *                                 not complete successfully.
449   * @param  alertOnStart            Indicates whether the server should send an
450   *                                 alert notification when this task starts.
451   * @param  alertOnSuccess          Indicates whether the server should send an
452   *                                 alert notification if this task completes
453   *                                 successfully.
454   * @param  alertOnError            Indicates whether the server should send an
455   *                                 alert notification if this task fails to
456   *                                 complete successfully.
457   */
458  public SearchTask(@Nullable final String taskID,
459              @NotNull final String baseDN,
460              @NotNull final SearchScope scope,
461              @NotNull final Filter filter,
462              @Nullable final List<String> attributes,
463              @NotNull final String outputFile,
464              @Nullable final String authzDN,
465              @Nullable final Date scheduledStartTime,
466              @Nullable final List<String> dependencyIDs,
467              @Nullable final FailedDependencyAction failedDependencyAction,
468              @Nullable final List<String> notifyOnStart,
469              @Nullable final List<String> notifyOnCompletion,
470              @Nullable final List<String> notifyOnSuccess,
471              @Nullable final List<String> notifyOnError,
472              @Nullable final Boolean alertOnStart,
473              @Nullable final Boolean alertOnSuccess,
474              @Nullable final Boolean alertOnError)
475  {
476    super(taskID, SEARCH_TASK_CLASS, scheduledStartTime, dependencyIDs,
477         failedDependencyAction, notifyOnStart, notifyOnCompletion,
478         notifyOnSuccess, notifyOnError, alertOnStart, alertOnSuccess,
479         alertOnError);
480
481    Validator.ensureNotNull(baseDN, scope, filter, outputFile);
482
483    this.baseDN     = baseDN;
484    this.scope      = scope;
485    this.filter     = filter;
486    this.outputFile = outputFile;
487    this.authzDN    = authzDN;
488
489    if (attributes == null)
490    {
491      this.attributes = Collections.emptyList();
492    }
493    else
494    {
495      this.attributes = Collections.unmodifiableList(attributes);
496    }
497  }
498
499
500
501  /**
502   * Creates a new search task from the provided entry.
503   *
504   * @param  entry  The entry to use to create this search task.
505   *
506   * @throws  TaskException  If the provided entry cannot be parsed as a search
507   *                         task entry.
508   */
509  public SearchTask(@NotNull final Entry entry)
510         throws TaskException
511  {
512    super(entry);
513
514
515    // Get the base DN.  It must be present.
516    baseDN = entry.getAttributeValue(ATTR_BASE_DN);
517    if (baseDN == null)
518    {
519      throw new TaskException(ERR_SEARCH_TASK_ENTRY_NO_BASE_DN.get(
520           entry.getDN()));
521    }
522
523
524    // Get the scope.  It must be present.
525    final String scopeStr =
526         StaticUtils.toLowerCase(entry.getAttributeValue(ATTR_SCOPE));
527    if (scopeStr == null)
528    {
529      throw new TaskException(ERR_SEARCH_TASK_ENTRY_NO_SCOPE.get(
530           entry.getDN()));
531    }
532
533    if (scopeStr.equals("base") || scopeStr.equals("baseobject") ||
534        scopeStr.equals("0"))
535    {
536      scope = SearchScope.BASE;
537    }
538    else if (scopeStr.equals("one") || scopeStr.equals("onelevel") ||
539             scopeStr.equals("singlelevel") || scopeStr.equals("1"))
540    {
541      scope = SearchScope.ONE;
542    }
543    else if (scopeStr.equals("sub") || scopeStr.equals("subtree") ||
544             scopeStr.equals("wholesubtree") || scopeStr.equals("2"))
545    {
546      scope = SearchScope.SUB;
547    }
548    else if (scopeStr.equals("subord") || scopeStr.equals("subordinate") ||
549             scopeStr.equals("subordinatesubtree") || scopeStr.equals("3"))
550    {
551      scope = SearchScope.SUBORDINATE_SUBTREE;
552    }
553    else
554    {
555      throw new TaskException(ERR_SEARCH_TASK_ENTRY_INVALID_SCOPE.get(
556           entry.getDN(), scopeStr));
557    }
558
559
560    // Get the filter.  It must be present.
561    final String filterStr = entry.getAttributeValue(ATTR_FILTER);
562    if (filterStr == null)
563    {
564      throw new TaskException(ERR_SEARCH_TASK_ENTRY_NO_FILTER.get(
565           entry.getDN()));
566    }
567    try
568    {
569      filter = Filter.create(filterStr);
570    }
571    catch (final LDAPException le)
572    {
573      Debug.debugException(le);
574      throw new TaskException(ERR_SEARCH_TASK_ENTRY_INVALID_FILTER.get(
575           entry.getDN(), filterStr), le);
576    }
577
578
579    // Get the list of requested attributes.  It is optional.
580    final String[] attrs = entry.getAttributeValues(ATTR_RETURN_ATTR);
581    if (attrs == null)
582    {
583      attributes = Collections.emptyList();
584    }
585    else
586    {
587      attributes = Collections.unmodifiableList(Arrays.asList(attrs));
588    }
589
590
591    // Get the authorization DN.  It is optional.
592    authzDN = entry.getAttributeValue(ATTR_AUTHZ_DN);
593
594
595    // Get the path to the output file.  It must be present.
596    outputFile = entry.getAttributeValue(ATTR_OUTPUT_FILE);
597    if (outputFile == null)
598    {
599      throw new TaskException(ERR_SEARCH_TASK_ENTRY_NO_OUTPUT_FILE.get(
600           entry.getDN()));
601    }
602  }
603
604
605
606  /**
607   * Creates a new search task from the provided set of task properties.
608   *
609   * @param  properties  The set of task properties and their corresponding
610   *                     values to use for the task.  It must not be
611   *                     {@code null}.
612   *
613   * @throws  TaskException  If the provided set of properties cannot be used to
614   *                         create a valid add schema file task.
615   */
616  public SearchTask(@NotNull final Map<TaskProperty,List<Object>> properties)
617         throws TaskException
618  {
619    super(SEARCH_TASK_CLASS, properties);
620
621    Filter      tmpFilter  = null;
622    SearchScope tmpScope   = null;
623    String      tmpAuthzDN = null;
624    String      tmpBaseDN  = null;
625    String      tmpFile    = null;
626    String[]    tmpAttrs   = null;
627
628    for (final Map.Entry<TaskProperty,List<Object>> entry :
629         properties.entrySet())
630    {
631      final TaskProperty p = entry.getKey();
632      final String attrName = StaticUtils.toLowerCase(p.getAttributeName());
633      final List<Object> values = entry.getValue();
634
635      if (attrName.equals(ATTR_BASE_DN))
636      {
637        tmpBaseDN = parseString(p, values, null);
638      }
639      else if (attrName.equals(ATTR_SCOPE))
640      {
641        final String scopeStr =
642             StaticUtils.toLowerCase(parseString(p, values, null));
643        if (scopeStr != null)
644        {
645          if (scopeStr.equals("base") || scopeStr.equals("baseobject") ||
646               scopeStr.equals("0"))
647          {
648            tmpScope = SearchScope.BASE;
649          }
650          else if (scopeStr.equals("one") || scopeStr.equals("onelevel") ||
651               scopeStr.equals("singlelevel") || scopeStr.equals("1"))
652          {
653            tmpScope = SearchScope.ONE;
654          }
655          else if (scopeStr.equals("sub") || scopeStr.equals("subtree") ||
656                   scopeStr.equals("wholesubtree") || scopeStr.equals("2"))
657          {
658            tmpScope = SearchScope.SUB;
659          }
660          else if (scopeStr.equals("subord") ||
661                   scopeStr.equals("subordinate") ||
662                   scopeStr.equals("subordinatesubtree") ||
663                   scopeStr.equals("3"))
664          {
665            tmpScope = SearchScope.SUBORDINATE_SUBTREE;
666          }
667          else
668          {
669            throw new TaskException(ERR_SEARCH_TASK_INVALID_SCOPE_PROPERTY.get(
670                 scopeStr));
671          }
672        }
673      }
674      else if (attrName.equals(ATTR_FILTER))
675      {
676        final String filterStr = parseString(p, values, null);
677        if (filterStr != null)
678        {
679          try
680          {
681            tmpFilter = Filter.create(filterStr);
682          }
683          catch (final LDAPException le)
684          {
685            Debug.debugException(le);
686            throw new TaskException(ERR_SEARCH_TASK_INVALID_FILTER_PROPERTY.get(
687                 filterStr), le);
688          }
689        }
690      }
691      else if (attrName.equals(ATTR_RETURN_ATTR))
692      {
693        tmpAttrs = parseStrings(p, values, null);
694      }
695      else if (attrName.equals(ATTR_OUTPUT_FILE))
696      {
697        tmpFile = parseString(p, values, null);
698      }
699      else if (attrName.equals(ATTR_AUTHZ_DN))
700      {
701        tmpAuthzDN = parseString(p, values, null);
702      }
703    }
704
705    baseDN = tmpBaseDN;
706    if (baseDN == null)
707    {
708      throw new TaskException(ERR_SEARCH_TASK_NO_BASE_PROPERTY.get());
709    }
710
711    scope = tmpScope;
712    if (scope == null)
713    {
714      throw new TaskException(ERR_SEARCH_TASK_NO_SCOPE_PROPERTY.get());
715    }
716
717    filter = tmpFilter;
718    if (filter == null)
719    {
720      throw new TaskException(ERR_SEARCH_TASK_NO_FILTER_PROPERTY.get());
721    }
722
723    outputFile = tmpFile;
724    if (outputFile == null)
725    {
726      throw new TaskException(ERR_SEARCH_TASK_NO_OUTPUT_FILE_PROPERTY.get());
727    }
728
729
730    if (tmpAttrs == null)
731    {
732      attributes = Collections.emptyList();
733    }
734    else
735    {
736      attributes = Collections.unmodifiableList(Arrays.asList(tmpAttrs));
737    }
738
739    authzDN = tmpAuthzDN;
740  }
741
742
743
744  /**
745   * {@inheritDoc}
746   */
747  @Override()
748  @NotNull()
749  public String getTaskName()
750  {
751    return INFO_TASK_NAME_SEARCH.get();
752  }
753
754
755
756  /**
757   * {@inheritDoc}
758   */
759  @Override()
760  @NotNull()
761  public String getTaskDescription()
762  {
763    return INFO_TASK_DESCRIPTION_SEARCH.get();
764  }
765
766
767
768  /**
769   * Retrieves the base DN for the search.
770   *
771   * @return  The base DN for the search.
772   */
773  @NotNull()
774  public String getBaseDN()
775  {
776    return baseDN;
777  }
778
779
780
781  /**
782   * Retrieves the scope for the search.
783   *
784   * @return  The scope for the search.
785   */
786  @NotNull()
787  public SearchScope getScope()
788  {
789    return scope;
790  }
791
792
793
794  /**
795   * Retrieves the filter for the search.
796   *
797   * @return  The filter for the search.
798   */
799  @NotNull()
800  public Filter getFilter()
801  {
802    return filter;
803  }
804
805
806
807  /**
808   * Retrieves the list of attributes to include in matching entries.
809   *
810   * @return  The list of attributes to include in matching entries, or an
811   *          empty list of all user attributes should be requested.
812   */
813  @NotNull()
814  public List<String> getAttributes()
815  {
816    return attributes;
817  }
818
819
820
821  /**
822   * Retrieves the DN of the user as whom the request should be processed.
823   *
824   * @return  The DN of the user as whom the request should be processed, or
825   *          {@code null} if it should be processed as an internal root user.
826   */
827  @Nullable()
828  public String getAuthzDN()
829  {
830    return authzDN;
831  }
832
833
834
835  /**
836   * Retrieves the path to the file on the server filesystem to which the
837   * results should be written.
838   *
839   * @return  The path to the file on the server filesystem to which the results
840   *          should be written.
841   */
842  @NotNull()
843  public String getOutputFile()
844  {
845    return outputFile;
846  }
847
848
849
850  /**
851   * {@inheritDoc}
852   */
853  @Override()
854  @NotNull()
855  protected List<String> getAdditionalObjectClasses()
856  {
857    return Collections.singletonList(OC_SEARCH_TASK);
858  }
859
860
861
862  /**
863   * {@inheritDoc}
864   */
865  @Override()
866  @NotNull()
867  protected List<Attribute> getAdditionalAttributes()
868  {
869    final LinkedList<Attribute> attrs = new LinkedList<>();
870
871    attrs.add(new Attribute(ATTR_BASE_DN, baseDN));
872    attrs.add(new Attribute(ATTR_SCOPE, String.valueOf(scope.intValue())));
873    attrs.add(new Attribute(ATTR_FILTER, filter.toString()));
874    attrs.add(new Attribute(ATTR_OUTPUT_FILE, outputFile));
875
876    if ((attributes != null) && (! attributes.isEmpty()))
877    {
878      attrs.add(new Attribute(ATTR_RETURN_ATTR, attributes));
879    }
880
881    if (authzDN != null)
882    {
883      attrs.add(new Attribute(ATTR_AUTHZ_DN, authzDN));
884    }
885
886    return Collections.unmodifiableList(attrs);
887  }
888
889
890
891  /**
892   * {@inheritDoc}
893   */
894  @Override()
895  @NotNull()
896  public List<TaskProperty> getTaskSpecificProperties()
897  {
898    final LinkedList<TaskProperty> props = new LinkedList<>();
899
900    props.add(PROPERTY_BASE_DN);
901    props.add(PROPERTY_SCOPE);
902    props.add(PROPERTY_FILTER);
903    props.add(PROPERTY_REQUESTED_ATTR);
904    props.add(PROPERTY_AUTHZ_DN);
905    props.add(PROPERTY_OUTPUT_FILE);
906
907    return Collections.unmodifiableList(props);
908  }
909
910
911
912  /**
913   * {@inheritDoc}
914   */
915  @Override()
916  @NotNull()
917  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
918  {
919    final LinkedHashMap<TaskProperty,List<Object>> props =
920         new LinkedHashMap<>(StaticUtils.computeMapCapacity(6));
921
922    props.put(PROPERTY_BASE_DN,
923         Collections.<Object>singletonList(baseDN));
924
925    props.put(PROPERTY_SCOPE,
926         Collections.<Object>singletonList(String.valueOf(scope.intValue())));
927
928    props.put(PROPERTY_FILTER,
929         Collections.<Object>singletonList(filter.toString()));
930
931    if ((attributes != null) && (! attributes.isEmpty()))
932    {
933      final LinkedList<Object> attrObjects = new LinkedList<>();
934      attrObjects.addAll(attributes);
935
936      props.put(PROPERTY_REQUESTED_ATTR,
937           Collections.unmodifiableList(attrObjects));
938    }
939
940    if (authzDN != null)
941    {
942      props.put(PROPERTY_AUTHZ_DN,
943           Collections.<Object>singletonList(authzDN));
944    }
945
946    props.put(PROPERTY_OUTPUT_FILE,
947         Collections.<Object>singletonList(outputFile));
948
949    props.putAll(super.getTaskPropertyValues());
950    return Collections.unmodifiableMap(props);
951  }
952}