Search in sources :

Example 6 with OutputFormat

use of com.unboundid.util.OutputFormat in project ldapsdk by pingidentity.

the class SearchAndModRate method doToolProcessing.

/**
 * Performs the actual processing for this tool.  In this case, it gets a
 * connection to the directory server and uses it to perform the requested
 * searches.
 *
 * @return  The result code for the processing that was performed.
 */
@Override()
@NotNull()
public ResultCode doToolProcessing() {
    // variable rate data file and return.
    if (sampleRateFile.isPresent()) {
        try {
            RateAdjustor.writeSampleVariableRateFile(sampleRateFile.getValue());
            return ResultCode.SUCCESS;
        } catch (final Exception e) {
            Debug.debugException(e);
            err("An error occurred while trying to write sample variable data " + "rate file '", sampleRateFile.getValue().getAbsolutePath(), "':  ", StaticUtils.getExceptionMessage(e));
            return ResultCode.LOCAL_ERROR;
        }
    }
    // Determine the random seed to use.
    final Long seed;
    if (randomSeed.isPresent()) {
        seed = Long.valueOf(randomSeed.getValue());
    } else {
        seed = null;
    }
    // Create value patterns for the base DN, filter, and proxied authorization
    // DN.
    final ValuePattern dnPattern;
    try {
        dnPattern = new ValuePattern(baseDN.getValue(), seed);
    } catch (final ParseException pe) {
        Debug.debugException(pe);
        err("Unable to parse the base DN value pattern:  ", pe.getMessage());
        return ResultCode.PARAM_ERROR;
    }
    final ValuePattern filterPattern;
    try {
        filterPattern = new ValuePattern(filter.getValue(), seed);
    } catch (final ParseException pe) {
        Debug.debugException(pe);
        err("Unable to parse the filter pattern:  ", pe.getMessage());
        return ResultCode.PARAM_ERROR;
    }
    final ValuePattern authzIDPattern;
    if (proxyAs.isPresent()) {
        try {
            authzIDPattern = new ValuePattern(proxyAs.getValue(), seed);
        } catch (final ParseException pe) {
            Debug.debugException(pe);
            err("Unable to parse the proxied authorization pattern:  ", pe.getMessage());
            return ResultCode.PARAM_ERROR;
        }
    } else {
        authzIDPattern = null;
    }
    // Get the set of controls to include in search requests.
    final ArrayList<Control> searchControls = new ArrayList<>(5);
    if (searchAssertionFilter.isPresent()) {
        searchControls.add(new AssertionRequestControl(searchAssertionFilter.getValue()));
    }
    if (searchControl.isPresent()) {
        searchControls.addAll(searchControl.getValues());
    }
    // Get the set of controls to include in modify requests.
    final ArrayList<Control> modifyControls = new ArrayList<>(5);
    if (modifyAssertionFilter.isPresent()) {
        modifyControls.add(new AssertionRequestControl(modifyAssertionFilter.getValue()));
    }
    if (permissiveModify.isPresent()) {
        modifyControls.add(new PermissiveModifyRequestControl());
    }
    if (preReadAttribute.isPresent()) {
        final List<String> attrList = preReadAttribute.getValues();
        final String[] attrArray = new String[attrList.size()];
        attrList.toArray(attrArray);
        modifyControls.add(new PreReadRequestControl(attrArray));
    }
    if (postReadAttribute.isPresent()) {
        final List<String> attrList = postReadAttribute.getValues();
        final String[] attrArray = new String[attrList.size()];
        attrList.toArray(attrArray);
        modifyControls.add(new PostReadRequestControl(attrArray));
    }
    if (modifyControl.isPresent()) {
        modifyControls.addAll(modifyControl.getValues());
    }
    // Get the attributes to return.
    final String[] returnAttrs;
    if (returnAttributes.isPresent()) {
        final List<String> attrList = returnAttributes.getValues();
        returnAttrs = new String[attrList.size()];
        attrList.toArray(returnAttrs);
    } else {
        returnAttrs = StaticUtils.NO_STRINGS;
    }
    // Get the names of the attributes to modify.
    final String[] modAttrs = new String[modifyAttributes.getValues().size()];
    modifyAttributes.getValues().toArray(modAttrs);
    // Get the character set as a byte array.
    final byte[] charSet = StaticUtils.getBytes(characterSet.getValue());
    // If the --ratePerSecond option was specified, then limit the rate
    // accordingly.
    FixedRateBarrier fixedRateBarrier = null;
    if (ratePerSecond.isPresent() || variableRateData.isPresent()) {
        // We might not have a rate per second if --variableRateData is specified.
        // The rate typically doesn't matter except when we have warm-up
        // intervals.  In this case, we'll run at the max rate.
        final int intervalSeconds = collectionInterval.getValue();
        final int ratePerInterval = (ratePerSecond.getValue() == null) ? Integer.MAX_VALUE : ratePerSecond.getValue() * intervalSeconds;
        fixedRateBarrier = new FixedRateBarrier(1000L * intervalSeconds, ratePerInterval);
    }
    // If --variableRateData was specified, then initialize a RateAdjustor.
    RateAdjustor rateAdjustor = null;
    if (variableRateData.isPresent()) {
        try {
            rateAdjustor = RateAdjustor.newInstance(fixedRateBarrier, ratePerSecond.getValue(), variableRateData.getValue());
        } catch (final IOException | IllegalArgumentException e) {
            Debug.debugException(e);
            err("Initializing the variable rates failed: " + e.getMessage());
            return ResultCode.PARAM_ERROR;
        }
    }
    // Determine whether to include timestamps in the output and if so what
    // format should be used for them.
    final boolean includeTimestamp;
    final String timeFormat;
    if (timestampFormat.getValue().equalsIgnoreCase("with-date")) {
        includeTimestamp = true;
        timeFormat = "dd/MM/yyyy HH:mm:ss";
    } else if (timestampFormat.getValue().equalsIgnoreCase("without-date")) {
        includeTimestamp = true;
        timeFormat = "HH:mm:ss";
    } else {
        includeTimestamp = false;
        timeFormat = null;
    }
    // Determine whether any warm-up intervals should be run.
    final long totalIntervals;
    final boolean warmUp;
    int remainingWarmUpIntervals = warmUpIntervals.getValue();
    if (remainingWarmUpIntervals > 0) {
        warmUp = true;
        totalIntervals = 0L + numIntervals.getValue() + remainingWarmUpIntervals;
    } else {
        warmUp = true;
        totalIntervals = 0L + numIntervals.getValue();
    }
    // Create the table that will be used to format the output.
    final OutputFormat outputFormat;
    if (csvFormat.isPresent()) {
        outputFormat = OutputFormat.CSV;
    } else {
        outputFormat = OutputFormat.COLUMNS;
    }
    final ColumnFormatter formatter = new ColumnFormatter(includeTimestamp, timeFormat, outputFormat, " ", new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Searches/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Srch Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Mods/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Mod Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Errors/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Searches/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Srch Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Mods/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Mod Dur ms"));
    // Create values to use for statistics collection.
    final AtomicLong searchCounter = new AtomicLong(0L);
    final AtomicLong errorCounter = new AtomicLong(0L);
    final AtomicLong modCounter = new AtomicLong(0L);
    final AtomicLong modDurations = new AtomicLong(0L);
    final AtomicLong searchDurations = new AtomicLong(0L);
    final ResultCodeCounter rcCounter = new ResultCodeCounter();
    // Determine the length of each interval in milliseconds.
    final long intervalMillis = 1000L * collectionInterval.getValue();
    // Create the threads to use for the searches.
    final Random random = new Random();
    final CyclicBarrier barrier = new CyclicBarrier(numThreads.getValue() + 1);
    final SearchAndModRateThread[] threads = new SearchAndModRateThread[numThreads.getValue()];
    for (int i = 0; i < threads.length; i++) {
        final LDAPConnection connection;
        try {
            connection = getConnection();
        } catch (final LDAPException le) {
            Debug.debugException(le);
            err("Unable to connect to the directory server:  ", StaticUtils.getExceptionMessage(le));
            return le.getResultCode();
        }
        threads[i] = new SearchAndModRateThread(this, i, connection, dnPattern, scopeArg.getValue(), filterPattern, returnAttrs, modAttrs, valueLength.getValue(), charSet, authzIDPattern, simplePageSize.getValue(), searchControls, modifyControls, iterationsBeforeReconnect.getValue(), random.nextLong(), runningThreads, barrier, searchCounter, modCounter, searchDurations, modDurations, errorCounter, rcCounter, fixedRateBarrier);
        threads[i].start();
    }
    // Display the table header.
    for (final String headerLine : formatter.getHeaderLines(true)) {
        out(headerLine);
    }
    // which case, we'll start it after the warm-up is complete.
    if ((rateAdjustor != null) && (remainingWarmUpIntervals <= 0)) {
        rateAdjustor.start();
    }
    // Indicate that the threads can start running.
    try {
        barrier.await();
    } catch (final Exception e) {
        Debug.debugException(e);
    }
    long overallStartTime = System.nanoTime();
    long nextIntervalStartTime = System.currentTimeMillis() + intervalMillis;
    boolean setOverallStartTime = false;
    long lastSearchDuration = 0L;
    long lastModDuration = 0L;
    long lastNumErrors = 0L;
    long lastNumSearches = 0L;
    long lastNumMods = 0L;
    long lastEndTime = System.nanoTime();
    for (long i = 0; i < totalIntervals; i++) {
        if (rateAdjustor != null) {
            if (!rateAdjustor.isAlive()) {
                out("All of the rates in " + variableRateData.getValue().getName() + " have been completed.");
                break;
            }
        }
        final long startTimeMillis = System.currentTimeMillis();
        final long sleepTimeMillis = nextIntervalStartTime - startTimeMillis;
        nextIntervalStartTime += intervalMillis;
        if (sleepTimeMillis > 0) {
            sleeper.sleep(sleepTimeMillis);
        }
        if (stopRequested.get()) {
            break;
        }
        final long endTime = System.nanoTime();
        final long intervalDuration = endTime - lastEndTime;
        final long numSearches;
        final long numMods;
        final long numErrors;
        final long totalSearchDuration;
        final long totalModDuration;
        if (warmUp && (remainingWarmUpIntervals > 0)) {
            numSearches = searchCounter.getAndSet(0L);
            numMods = modCounter.getAndSet(0L);
            numErrors = errorCounter.getAndSet(0L);
            totalSearchDuration = searchDurations.getAndSet(0L);
            totalModDuration = modDurations.getAndSet(0L);
        } else {
            numSearches = searchCounter.get();
            numMods = modCounter.get();
            numErrors = errorCounter.get();
            totalSearchDuration = searchDurations.get();
            totalModDuration = modDurations.get();
        }
        final long recentNumSearches = numSearches - lastNumSearches;
        final long recentNumMods = numMods - lastNumMods;
        final long recentNumErrors = numErrors - lastNumErrors;
        final long recentSearchDuration = totalSearchDuration - lastSearchDuration;
        final long recentModDuration = totalModDuration - lastModDuration;
        final double numSeconds = intervalDuration / 1_000_000_000.0d;
        final double recentSearchRate = recentNumSearches / numSeconds;
        final double recentModRate = recentNumMods / numSeconds;
        final double recentErrorRate = recentNumErrors / numSeconds;
        final double recentAvgSearchDuration;
        if (recentNumSearches > 0L) {
            recentAvgSearchDuration = 1.0d * recentSearchDuration / recentNumSearches / 1_000_000;
        } else {
            recentAvgSearchDuration = 0.0d;
        }
        final double recentAvgModDuration;
        if (recentNumMods > 0L) {
            recentAvgModDuration = 1.0d * recentModDuration / recentNumMods / 1_000_000;
        } else {
            recentAvgModDuration = 0.0d;
        }
        if (warmUp && (remainingWarmUpIntervals > 0)) {
            out(formatter.formatRow(recentSearchRate, recentAvgSearchDuration, recentModRate, recentAvgModDuration, recentErrorRate, "warming up", "warming up", "warming up", "warming up"));
            remainingWarmUpIntervals--;
            if (remainingWarmUpIntervals == 0) {
                out("Warm-up completed.  Beginning overall statistics collection.");
                setOverallStartTime = true;
                if (rateAdjustor != null) {
                    rateAdjustor.start();
                }
            }
        } else {
            if (setOverallStartTime) {
                overallStartTime = lastEndTime;
                setOverallStartTime = false;
            }
            final double numOverallSeconds = (endTime - overallStartTime) / 1_000_000_000.0d;
            final double overallSearchRate = numSearches / numOverallSeconds;
            final double overallModRate = numMods / numOverallSeconds;
            final double overallAvgSearchDuration;
            if (numSearches > 0L) {
                overallAvgSearchDuration = 1.0d * totalSearchDuration / numSearches / 1_000_000;
            } else {
                overallAvgSearchDuration = 0.0d;
            }
            final double overallAvgModDuration;
            if (numMods > 0L) {
                overallAvgModDuration = 1.0d * totalModDuration / numMods / 1_000_000;
            } else {
                overallAvgModDuration = 0.0d;
            }
            out(formatter.formatRow(recentSearchRate, recentAvgSearchDuration, recentModRate, recentAvgModDuration, recentErrorRate, overallSearchRate, overallAvgSearchDuration, overallModRate, overallAvgModDuration));
            lastNumSearches = numSearches;
            lastNumMods = numMods;
            lastNumErrors = numErrors;
            lastSearchDuration = totalSearchDuration;
            lastModDuration = totalModDuration;
        }
        final List<ObjectPair<ResultCode, Long>> rcCounts = rcCounter.getCounts(true);
        if ((!suppressErrors.isPresent()) && (!rcCounts.isEmpty())) {
            err("\tError Results:");
            for (final ObjectPair<ResultCode, Long> p : rcCounts) {
                err("\t", p.getFirst().getName(), ":  ", p.getSecond());
            }
        }
        lastEndTime = endTime;
    }
    // Shut down the RateAdjustor if we have one.
    if (rateAdjustor != null) {
        rateAdjustor.shutDown();
    }
    // Stop all of the threads.
    ResultCode resultCode = ResultCode.SUCCESS;
    for (final SearchAndModRateThread t : threads) {
        final ResultCode r = t.stopRunning();
        if (resultCode == ResultCode.SUCCESS) {
            resultCode = r;
        }
    }
    return resultCode;
}
Also used : ValuePattern(com.unboundid.util.ValuePattern) ArrayList(java.util.ArrayList) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) Control(com.unboundid.ldap.sdk.Control) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) FormattableColumn(com.unboundid.util.FormattableColumn) Random(java.util.Random) ColumnFormatter(com.unboundid.util.ColumnFormatter) OutputFormat(com.unboundid.util.OutputFormat) RateAdjustor(com.unboundid.util.RateAdjustor) IOException(java.io.IOException) LDAPConnection(com.unboundid.ldap.sdk.LDAPConnection) ResultCodeCounter(com.unboundid.util.ResultCodeCounter) ParseException(java.text.ParseException) ArgumentException(com.unboundid.util.args.ArgumentException) LDAPException(com.unboundid.ldap.sdk.LDAPException) IOException(java.io.IOException) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicLong(java.util.concurrent.atomic.AtomicLong) LDAPException(com.unboundid.ldap.sdk.LDAPException) AtomicLong(java.util.concurrent.atomic.AtomicLong) FixedRateBarrier(com.unboundid.util.FixedRateBarrier) ParseException(java.text.ParseException) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) ResultCode(com.unboundid.ldap.sdk.ResultCode) ObjectPair(com.unboundid.util.ObjectPair) NotNull(com.unboundid.util.NotNull)

Example 7 with OutputFormat

use of com.unboundid.util.OutputFormat in project ldapsdk by pingidentity.

the class LDAPSearch method doExtendedNonLDAPArgumentValidation.

/**
 * {@inheritDoc}
 */
@Override()
public void doExtendedNonLDAPArgumentValidation() throws ArgumentException {
    // was provided, then use that.
    if (wrapColumn.isPresent()) {
        final int wc = wrapColumn.getValue();
        if (wc <= 0) {
            WRAP_COLUMN = Integer.MAX_VALUE;
        } else {
            WRAP_COLUMN = wc;
        }
    } else if (dontWrap.isPresent()) {
        WRAP_COLUMN = Integer.MAX_VALUE;
    }
    // If the ldapURLFile argument was provided, then there must not be any
    // trailing arguments.
    final List<String> trailingArgs = parser.getTrailingArguments();
    if (ldapURLFile.isPresent()) {
        if (!trailingArgs.isEmpty()) {
            throw new ArgumentException(ERR_LDAPSEARCH_TRAILING_ARGS_WITH_URL_FILE.get(ldapURLFile.getIdentifierString()));
        }
    }
    // not be a filter.
    if (filter.isPresent() || filterFile.isPresent()) {
        if (!trailingArgs.isEmpty()) {
            try {
                Filter.create(trailingArgs.get(0));
                throw new ArgumentException(ERR_LDAPSEARCH_TRAILING_FILTER_WITH_FILTER_FILE.get(filterFile.getIdentifierString()));
            } catch (final LDAPException le) {
            // This is the normal condition.  Not even worth debugging the
            // exception.
            }
        }
    }
    // argument must be a valid search filter.
    if (!(ldapURLFile.isPresent() || filter.isPresent() || filterFile.isPresent())) {
        if (trailingArgs.isEmpty()) {
            throw new ArgumentException(ERR_LDAPSEARCH_NO_TRAILING_ARGS.get(filterFile.getIdentifierString(), ldapURLFile.getIdentifierString()));
        }
        try {
            Filter.create(trailingArgs.get(0));
        } catch (final Exception e) {
            Debug.debugException(e);
            throw new ArgumentException(ERR_LDAPSEARCH_FIRST_TRAILING_ARG_NOT_FILTER.get(trailingArgs.get(0)), e);
        }
    }
    // fail.
    for (final String s : trailingArgs) {
        if (s.startsWith("-")) {
            commentToErr(WARN_LDAPSEARCH_TRAILING_ARG_STARTS_WITH_DASH.get(s));
            break;
        }
    }
    // pre-create the matched values request control.
    if (matchedValuesFilter.isPresent()) {
        final List<Filter> filterList = matchedValuesFilter.getValues();
        final MatchedValuesFilter[] matchedValuesFilters = new MatchedValuesFilter[filterList.size()];
        for (int i = 0; i < matchedValuesFilters.length; i++) {
            try {
                matchedValuesFilters[i] = MatchedValuesFilter.create(filterList.get(i));
            } catch (final Exception e) {
                Debug.debugException(e);
                throw new ArgumentException(ERR_LDAPSEARCH_INVALID_MATCHED_VALUES_FILTER.get(filterList.get(i).toString()), e);
            }
        }
        matchedValuesRequestControl = new MatchedValuesRequestControl(true, matchedValuesFilters);
    }
    // the argument value and pre-create the control.
    if (matchingEntryCountControl.isPresent()) {
        final MatchingEntryCountRequestControlProperties properties = new MatchingEntryCountRequestControlProperties();
        Integer examineCount = null;
        try {
            for (final String element : matchingEntryCountControl.getValue().toLowerCase().split(":")) {
                if (element.startsWith("examinecount=")) {
                    examineCount = Integer.parseInt(element.substring(13));
                } else if (element.equals("allowunindexed")) {
                    properties.setProcessSearchIfUnindexed(true);
                } else if (element.equals("alwaysexamine")) {
                    properties.setAlwaysExamineCandidates(true);
                } else if (element.equals("skipresolvingexplodedindexes")) {
                    properties.setSkipResolvingExplodedIndexes(true);
                } else if (element.startsWith("fastshortcircuitthreshold=")) {
                    properties.setFastShortCircuitThreshold(Long.parseLong(element.substring(26)));
                } else if (element.startsWith("slowshortcircuitthreshold=")) {
                    properties.setSlowShortCircuitThreshold(Long.parseLong(element.substring(26)));
                } else if (element.equals("extendedresponsedata")) {
                    properties.setIncludeExtendedResponseData(true);
                } else if (element.equals("debug")) {
                    properties.setIncludeDebugInfo(true);
                } else {
                    throw new ArgumentException(ERR_LDAPSEARCH_MATCHING_ENTRY_COUNT_INVALID_VALUE.get(matchingEntryCountControl.getIdentifierString()));
                }
            }
        } catch (final ArgumentException ae) {
            Debug.debugException(ae);
            throw ae;
        } catch (final Exception e) {
            Debug.debugException(e);
            throw new ArgumentException(ERR_LDAPSEARCH_MATCHING_ENTRY_COUNT_INVALID_VALUE.get(matchingEntryCountControl.getIdentifierString()), e);
        }
        if (examineCount == null) {
            throw new ArgumentException(ERR_LDAPSEARCH_MATCHING_ENTRY_COUNT_INVALID_VALUE.get(matchingEntryCountControl.getIdentifierString()));
        } else {
            properties.setMaxCandidatesToExamine(examineCount);
        }
        matchingEntryCountRequestControl = new MatchingEntryCountRequestControl(true, properties);
    }
    // validate the provided values.
    if (overrideSearchLimit.isPresent()) {
        final LinkedHashMap<String, String> properties = new LinkedHashMap<>(StaticUtils.computeMapCapacity(10));
        for (final String value : overrideSearchLimit.getValues()) {
            final int equalPos = value.indexOf('=');
            if (equalPos < 0) {
                throw new ArgumentException(ERR_LDAPSEARCH_OVERRIDE_LIMIT_NO_EQUAL.get(overrideSearchLimit.getIdentifierString()));
            } else if (equalPos == 0) {
                throw new ArgumentException(ERR_LDAPSEARCH_OVERRIDE_LIMIT_EMPTY_PROPERTY_NAME.get(overrideSearchLimit.getIdentifierString()));
            }
            final String propertyName = value.substring(0, equalPos);
            if (properties.containsKey(propertyName)) {
                throw new ArgumentException(ERR_LDAPSEARCH_OVERRIDE_LIMIT_DUPLICATE_PROPERTY_NAME.get(overrideSearchLimit.getIdentifierString(), propertyName));
            }
            if (equalPos == (value.length() - 1)) {
                throw new ArgumentException(ERR_LDAPSEARCH_OVERRIDE_LIMIT_EMPTY_PROPERTY_VALUE.get(overrideSearchLimit.getIdentifierString(), propertyName));
            }
            properties.put(propertyName, value.substring(equalPos + 1));
        }
        overrideSearchLimitsRequestControl = new OverrideSearchLimitsRequestControl(properties, false);
    }
    // the argument value and pre-create the control.
    if (persistentSearch.isPresent()) {
        boolean changesOnly = true;
        boolean returnECs = true;
        EnumSet<PersistentSearchChangeType> changeTypes = EnumSet.allOf(PersistentSearchChangeType.class);
        try {
            final String[] elements = persistentSearch.getValue().toLowerCase().split(":");
            if (elements.length == 0) {
                throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()));
            }
            final String header = StaticUtils.toLowerCase(elements[0]);
            if (!(header.equals("ps") || header.equals("persist") || header.equals("persistent") || header.equals("psearch") || header.equals("persistentsearch"))) {
                throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()));
            }
            if (elements.length > 1) {
                final String ctString = StaticUtils.toLowerCase(elements[1]);
                if (ctString.equals("any")) {
                    changeTypes = EnumSet.allOf(PersistentSearchChangeType.class);
                } else {
                    changeTypes.clear();
                    for (final String t : ctString.split(",")) {
                        if (t.equals("add")) {
                            changeTypes.add(PersistentSearchChangeType.ADD);
                        } else if (t.equals("del") || t.equals("delete")) {
                            changeTypes.add(PersistentSearchChangeType.DELETE);
                        } else if (t.equals("mod") || t.equals("modify")) {
                            changeTypes.add(PersistentSearchChangeType.MODIFY);
                        } else if (t.equals("moddn") || t.equals("modrdn") || t.equals("modifydn") || t.equals("modifyrdn")) {
                            changeTypes.add(PersistentSearchChangeType.MODIFY_DN);
                        } else {
                            throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()));
                        }
                    }
                }
            }
            if (elements.length > 2) {
                if (elements[2].equalsIgnoreCase("true") || elements[2].equals("1")) {
                    changesOnly = true;
                } else if (elements[2].equalsIgnoreCase("false") || elements[2].equals("0")) {
                    changesOnly = false;
                } else {
                    throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()));
                }
            }
            if (elements.length > 3) {
                if (elements[3].equalsIgnoreCase("true") || elements[3].equals("1")) {
                    returnECs = true;
                } else if (elements[3].equalsIgnoreCase("false") || elements[3].equals("0")) {
                    returnECs = false;
                } else {
                    throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()));
                }
            }
        } catch (final ArgumentException ae) {
            Debug.debugException(ae);
            throw ae;
        } catch (final Exception e) {
            Debug.debugException(e);
            throw new ArgumentException(ERR_LDAPSEARCH_PERSISTENT_SEARCH_INVALID_VALUE.get(persistentSearch.getIdentifierString()), e);
        }
        persistentSearchRequestControl = new PersistentSearchRequestControl(changeTypes, changesOnly, returnECs, true);
    }
    // sort order and pre-create the control.
    if (sortOrder.isPresent()) {
        final ArrayList<SortKey> sortKeyList = new ArrayList<>(5);
        final StringTokenizer tokenizer = new StringTokenizer(sortOrder.getValue(), ", ");
        while (tokenizer.hasMoreTokens()) {
            final String token = tokenizer.nextToken();
            final boolean ascending;
            String attributeName;
            if (token.startsWith("-")) {
                ascending = false;
                attributeName = token.substring(1);
            } else if (token.startsWith("+")) {
                ascending = true;
                attributeName = token.substring(1);
            } else {
                ascending = true;
                attributeName = token;
            }
            final String matchingRuleID;
            final int colonPos = attributeName.indexOf(':');
            if (colonPos >= 0) {
                matchingRuleID = attributeName.substring(colonPos + 1);
                attributeName = attributeName.substring(0, colonPos);
            } else {
                matchingRuleID = null;
            }
            final StringBuilder invalidReason = new StringBuilder();
            if (!PersistUtils.isValidLDAPName(attributeName, false, invalidReason)) {
                throw new ArgumentException(ERR_LDAPSEARCH_SORT_ORDER_INVALID_VALUE.get(sortOrder.getIdentifierString()));
            }
            sortKeyList.add(new SortKey(attributeName, matchingRuleID, (!ascending)));
        }
        if (sortKeyList.isEmpty()) {
            throw new ArgumentException(ERR_LDAPSEARCH_SORT_ORDER_INVALID_VALUE.get(sortOrder.getIdentifierString()));
        }
        final SortKey[] sortKeyArray = new SortKey[sortKeyList.size()];
        sortKeyList.toArray(sortKeyArray);
        sortRequestControl = new ServerSideSortRequestControl(sortKeyArray);
    }
    // argument value and pre-create the control.
    if (virtualListView.isPresent()) {
        try {
            final String[] elements = virtualListView.getValue().split(":");
            if (elements.length == 4) {
                vlvRequestControl = new VirtualListViewRequestControl(Integer.parseInt(elements[2]), Integer.parseInt(elements[0]), Integer.parseInt(elements[1]), Integer.parseInt(elements[3]), null);
            } else if (elements.length == 3) {
                vlvRequestControl = new VirtualListViewRequestControl(elements[2], Integer.parseInt(elements[0]), Integer.parseInt(elements[1]), null);
            } else {
                throw new ArgumentException(ERR_LDAPSEARCH_VLV_INVALID_VALUE.get(virtualListView.getIdentifierString()));
            }
        } catch (final ArgumentException ae) {
            Debug.debugException(ae);
            throw ae;
        } catch (final Exception e) {
            Debug.debugException(e);
            throw new ArgumentException(ERR_LDAPSEARCH_VLV_INVALID_VALUE.get(virtualListView.getIdentifierString()), e);
        }
    }
    // pre-create that control.
    if (joinRule.isPresent()) {
        final JoinRule rule;
        try {
            final String[] elements = joinRule.getValue().toLowerCase().split(":");
            final String ruleName = StaticUtils.toLowerCase(elements[0]);
            if (ruleName.equals("dn")) {
                rule = JoinRule.createDNJoin(elements[1]);
            } else if (ruleName.equals("reverse-dn") || ruleName.equals("reversedn")) {
                rule = JoinRule.createReverseDNJoin(elements[1]);
            } else if (ruleName.equals("equals") || ruleName.equals("equality")) {
                rule = JoinRule.createEqualityJoin(elements[1], elements[2], false);
            } else if (ruleName.equals("contains") || ruleName.equals("substring")) {
                rule = JoinRule.createContainsJoin(elements[1], elements[2], false);
            } else {
                throw new ArgumentException(ERR_LDAPSEARCH_JOIN_RULE_INVALID_VALUE.get(joinRule.getIdentifierString()));
            }
        } catch (final ArgumentException ae) {
            Debug.debugException(ae);
            throw ae;
        } catch (final Exception e) {
            Debug.debugException(e);
            throw new ArgumentException(ERR_LDAPSEARCH_JOIN_RULE_INVALID_VALUE.get(joinRule.getIdentifierString()), e);
        }
        final JoinBaseDN joinBase;
        if (joinBaseDN.isPresent()) {
            final String s = StaticUtils.toLowerCase(joinBaseDN.getValue());
            if (s.equals("search-base") || s.equals("search-base-dn")) {
                joinBase = JoinBaseDN.createUseSearchBaseDN();
            } else if (s.equals("source-entry-dn") || s.equals("source-dn")) {
                joinBase = JoinBaseDN.createUseSourceEntryDN();
            } else {
                try {
                    final DN dn = new DN(joinBaseDN.getValue());
                    joinBase = JoinBaseDN.createUseCustomBaseDN(joinBaseDN.getValue());
                } catch (final Exception e) {
                    Debug.debugException(e);
                    throw new ArgumentException(ERR_LDAPSEARCH_JOIN_BASE_DN_INVALID_VALUE.get(joinBaseDN.getIdentifierString()), e);
                }
            }
        } else {
            joinBase = JoinBaseDN.createUseSearchBaseDN();
        }
        final String[] joinAttrs;
        if (joinRequestedAttribute.isPresent()) {
            final List<String> valueList = joinRequestedAttribute.getValues();
            joinAttrs = new String[valueList.size()];
            valueList.toArray(joinAttrs);
        } else {
            joinAttrs = null;
        }
        joinRequestControl = new JoinRequestControl(new JoinRequestValue(rule, joinBase, joinScope.getValue(), DereferencePolicy.NEVER, joinSizeLimit.getValue(), joinFilter.getValue(), joinAttrs, joinRequireMatch.isPresent(), null));
    }
    // and pre-create those controls.
    if (routeToBackendSet.isPresent()) {
        final List<String> values = routeToBackendSet.getValues();
        final Map<String, List<String>> idsByRP = new LinkedHashMap<>(StaticUtils.computeMapCapacity(values.size()));
        for (final String value : values) {
            final int colonPos = value.indexOf(':');
            if (colonPos <= 0) {
                throw new ArgumentException(ERR_LDAPSEARCH_ROUTE_TO_BACKEND_SET_INVALID_FORMAT.get(value, routeToBackendSet.getIdentifierString()));
            }
            final String rpID = value.substring(0, colonPos);
            final String bsID = value.substring(colonPos + 1);
            List<String> idsForRP = idsByRP.get(rpID);
            if (idsForRP == null) {
                idsForRP = new ArrayList<>(values.size());
                idsByRP.put(rpID, idsForRP);
            }
            idsForRP.add(bsID);
        }
        for (final Map.Entry<String, List<String>> e : idsByRP.entrySet()) {
            final String rpID = e.getKey();
            final List<String> bsIDs = e.getValue();
            routeToBackendSetRequestControls.add(RouteToBackendSetRequestControl.createAbsoluteRoutingRequest(true, rpID, bsIDs));
        }
    }
    // Parse the dereference policy.
    final String derefStr = StaticUtils.toLowerCase(dereferencePolicy.getValue());
    if (derefStr.equals("always")) {
        derefPolicy = DereferencePolicy.ALWAYS;
    } else if (derefStr.equals("search")) {
        derefPolicy = DereferencePolicy.SEARCHING;
    } else if (derefStr.equals("find")) {
        derefPolicy = DereferencePolicy.FINDING;
    } else {
        derefPolicy = DereferencePolicy.NEVER;
    }
    // See if any entry transformations need to be applied.
    final ArrayList<EntryTransformation> transformations = new ArrayList<>(5);
    if (excludeAttribute.isPresent()) {
        transformations.add(new ExcludeAttributeTransformation(null, excludeAttribute.getValues()));
    }
    if (redactAttribute.isPresent()) {
        transformations.add(new RedactAttributeTransformation(null, true, (!hideRedactedValueCount.isPresent()), redactAttribute.getValues()));
    }
    if (scrambleAttribute.isPresent()) {
        final Long randomSeed;
        if (scrambleRandomSeed.isPresent()) {
            randomSeed = scrambleRandomSeed.getValue().longValue();
        } else {
            randomSeed = null;
        }
        transformations.add(new ScrambleAttributeTransformation(null, randomSeed, true, scrambleAttribute.getValues(), scrambleJSONField.getValues()));
    }
    if (renameAttributeFrom.isPresent()) {
        if (renameAttributeFrom.getNumOccurrences() != renameAttributeTo.getNumOccurrences()) {
            throw new ArgumentException(ERR_LDAPSEARCH_RENAME_ATTRIBUTE_MISMATCH.get());
        }
        final Iterator<String> sourceIterator = renameAttributeFrom.getValues().iterator();
        final Iterator<String> targetIterator = renameAttributeTo.getValues().iterator();
        while (sourceIterator.hasNext()) {
            transformations.add(new RenameAttributeTransformation(null, sourceIterator.next(), targetIterator.next(), true));
        }
    }
    if (moveSubtreeFrom.isPresent()) {
        if (moveSubtreeFrom.getNumOccurrences() != moveSubtreeTo.getNumOccurrences()) {
            throw new ArgumentException(ERR_LDAPSEARCH_MOVE_SUBTREE_MISMATCH.get());
        }
        final Iterator<DN> sourceIterator = moveSubtreeFrom.getValues().iterator();
        final Iterator<DN> targetIterator = moveSubtreeTo.getValues().iterator();
        while (sourceIterator.hasNext()) {
            transformations.add(new MoveSubtreeTransformation(sourceIterator.next(), targetIterator.next()));
        }
    }
    if (!transformations.isEmpty()) {
        entryTransformations = transformations;
    }
    // Create the result writer.
    final String outputFormatStr = StaticUtils.toLowerCase(outputFormat.getValue());
    if (outputFormatStr.equals("json")) {
        resultWriter = new JSONLDAPResultWriter(getOutStream());
    } else if (outputFormatStr.equals("csv") || outputFormatStr.equals("multi-valued-csv") || outputFormatStr.equals("tab-delimited") || outputFormatStr.equals("multi-valued-tab-delimited")) {
        // These output formats cannot be used with the --ldapURLFile argument.
        if (ldapURLFile.isPresent()) {
            throw new ArgumentException(ERR_LDAPSEARCH_OUTPUT_FORMAT_NOT_SUPPORTED_WITH_URLS.get(outputFormat.getValue(), ldapURLFile.getIdentifierString()));
        }
        // These output formats require the requested attributes to be specified
        // via the --requestedAttribute argument rather than as unnamed trailing
        // arguments.
        final List<String> requestedAttributes = requestedAttribute.getValues();
        if ((requestedAttributes == null) || requestedAttributes.isEmpty()) {
            throw new ArgumentException(ERR_LDAPSEARCH_OUTPUT_FORMAT_REQUIRES_REQUESTED_ATTR_ARG.get(outputFormat.getValue(), requestedAttribute.getIdentifierString()));
        }
        switch(trailingArgs.size()) {
            case 0:
                // This is fine.
                break;
            case 1:
                // filter nor filterFile argument was provided.
                if (filter.isPresent() || filterFile.isPresent()) {
                    throw new ArgumentException(ERR_LDAPSEARCH_OUTPUT_FORMAT_REQUIRES_REQUESTED_ATTR_ARG.get(outputFormat.getValue(), requestedAttribute.getIdentifierString()));
                }
                break;
            default:
                throw new ArgumentException(ERR_LDAPSEARCH_OUTPUT_FORMAT_REQUIRES_REQUESTED_ATTR_ARG.get(outputFormat.getValue(), requestedAttribute.getIdentifierString()));
        }
        final OutputFormat format;
        final boolean includeAllValues;
        switch(outputFormatStr) {
            case "multi-valued-csv":
                format = OutputFormat.CSV;
                includeAllValues = true;
                break;
            case "tab-delimited":
                format = OutputFormat.TAB_DELIMITED_TEXT;
                includeAllValues = false;
                break;
            case "multi-valued-tab-delimited":
                format = OutputFormat.TAB_DELIMITED_TEXT;
                includeAllValues = true;
                break;
            case "csv":
            default:
                format = OutputFormat.CSV;
                includeAllValues = false;
                break;
        }
        resultWriter = new ColumnBasedLDAPResultWriter(getOutStream(), format, requestedAttributes, WRAP_COLUMN, includeAllValues);
    } else if (outputFormatStr.equals("dns-only")) {
        resultWriter = new DNsOnlyLDAPResultWriter(getOutStream());
    } else if (outputFormatStr.equals("values-only")) {
        resultWriter = new ValuesOnlyLDAPResultWriter(getOutStream());
    } else {
        resultWriter = new LDIFLDAPResultWriter(getOutStream(), WRAP_COLUMN);
    }
}
Also used : ArrayList(java.util.ArrayList) JoinBaseDN(com.unboundid.ldap.sdk.unboundidds.controls.JoinBaseDN) DN(com.unboundid.ldap.sdk.DN) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) PersistentSearchRequestControl(com.unboundid.ldap.sdk.controls.PersistentSearchRequestControl) LinkedHashMap(java.util.LinkedHashMap) JoinRequestValue(com.unboundid.ldap.sdk.unboundidds.controls.JoinRequestValue) EntryTransformation(com.unboundid.ldap.sdk.transformations.EntryTransformation) ArrayList(java.util.ArrayList) List(java.util.List) ArgumentException(com.unboundid.util.args.ArgumentException) MatchingEntryCountRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.MatchingEntryCountRequestControl) RenameAttributeTransformation(com.unboundid.ldap.sdk.transformations.RenameAttributeTransformation) JoinRule(com.unboundid.ldap.sdk.unboundidds.controls.JoinRule) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) MoveSubtreeTransformation(com.unboundid.ldap.sdk.transformations.MoveSubtreeTransformation) ExcludeAttributeTransformation(com.unboundid.ldap.sdk.transformations.ExcludeAttributeTransformation) LDAPException(com.unboundid.ldap.sdk.LDAPException) AtomicLong(java.util.concurrent.atomic.AtomicLong) RedactAttributeTransformation(com.unboundid.ldap.sdk.transformations.RedactAttributeTransformation) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) MatchedValuesRequestControl(com.unboundid.ldap.sdk.controls.MatchedValuesRequestControl) SortKey(com.unboundid.ldap.sdk.controls.SortKey) JoinBaseDN(com.unboundid.ldap.sdk.unboundidds.controls.JoinBaseDN) MatchedValuesFilter(com.unboundid.ldap.sdk.controls.MatchedValuesFilter) OverrideSearchLimitsRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OverrideSearchLimitsRequestControl) ScrambleAttributeTransformation(com.unboundid.ldap.sdk.transformations.ScrambleAttributeTransformation) OutputFormat(com.unboundid.util.OutputFormat) LDAPSearchException(com.unboundid.ldap.sdk.LDAPSearchException) ArgumentException(com.unboundid.util.args.ArgumentException) LDAPException(com.unboundid.ldap.sdk.LDAPException) IOException(java.io.IOException) JoinRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.JoinRequestControl) StringTokenizer(java.util.StringTokenizer) Filter(com.unboundid.ldap.sdk.Filter) MatchedValuesFilter(com.unboundid.ldap.sdk.controls.MatchedValuesFilter) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) MatchingEntryCountRequestControlProperties(com.unboundid.ldap.sdk.unboundidds.controls.MatchingEntryCountRequestControlProperties) PersistentSearchChangeType(com.unboundid.ldap.sdk.controls.PersistentSearchChangeType)

Aggregations

OutputFormat (com.unboundid.util.OutputFormat)7 LDAPException (com.unboundid.ldap.sdk.LDAPException)6 ArgumentException (com.unboundid.util.args.ArgumentException)6 ArrayList (java.util.ArrayList)6 ResultCode (com.unboundid.ldap.sdk.ResultCode)5 ColumnFormatter (com.unboundid.util.ColumnFormatter)5 FormattableColumn (com.unboundid.util.FormattableColumn)5 NotNull (com.unboundid.util.NotNull)5 IOException (java.io.IOException)5 AtomicLong (java.util.concurrent.atomic.AtomicLong)5 Control (com.unboundid.ldap.sdk.Control)4 LDAPConnection (com.unboundid.ldap.sdk.LDAPConnection)4 FixedRateBarrier (com.unboundid.util.FixedRateBarrier)4 ObjectPair (com.unboundid.util.ObjectPair)4 RateAdjustor (com.unboundid.util.RateAdjustor)4 ResultCodeCounter (com.unboundid.util.ResultCodeCounter)4 ValuePattern (com.unboundid.util.ValuePattern)4 ParseException (java.text.ParseException)4 CyclicBarrier (java.util.concurrent.CyclicBarrier)4 AssertionRequestControl (com.unboundid.ldap.sdk.controls.AssertionRequestControl)3