com.unboundid.ldap.sdk.transformations.MoveSubtreeTransformation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unboundid-ldapsdk Show documentation
Show all versions of unboundid-ldapsdk Show documentation
The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use
Java API for communicating with LDAP directory servers and performing
related tasks like reading and writing LDIF, encoding and decoding data
using base64 and ASN.1 BER, and performing secure communication. This
package contains the Standard Edition of the LDAP SDK, which is a
complete, general-purpose library for communicating with LDAPv3 directory
servers.
/*
* Copyright 2016-2022 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright 2016-2022 Ping Identity Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2016-2022 Ping Identity Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk.transformations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.Modification;
import com.unboundid.ldap.sdk.RDN;
import com.unboundid.ldif.LDIFAddChangeRecord;
import com.unboundid.ldif.LDIFChangeRecord;
import com.unboundid.ldif.LDIFDeleteChangeRecord;
import com.unboundid.ldif.LDIFModifyChangeRecord;
import com.unboundid.ldif.LDIFModifyDNChangeRecord;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
/**
* This class provides an implementation of an entry and LDIF change record
* transformation that will alter DNs at or below a specified base DN to replace
* that base DN with a different base DN. This replacement will be applied to
* the DNs of entries that are transformed, as well as in any attribute values
* that represent DNs at or below the specified base DN.
*/
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class MoveSubtreeTransformation
implements EntryTransformation, LDIFChangeRecordTransformation
{
// The source base DN to be replaced.
@NotNull private final DN sourceDN;
// A list of the RDNs in the target base DN.
@NotNull private final List targetRDNs;
/**
* Creates a new move subtree transformation with the provided information.
*
* @param sourceDN The source base DN to be replaced with the target base
* DN. It must not be {@code null}.
* @param targetDN The target base DN to use to replace the source base DN.
* It must not be {@code null}.
*/
public MoveSubtreeTransformation(@NotNull final DN sourceDN,
@NotNull final DN targetDN)
{
this.sourceDN = sourceDN;
targetRDNs = Arrays.asList(targetDN.getRDNs());
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public Entry transformEntry(@NotNull final Entry e)
{
if (e == null)
{
return null;
}
// Iterate through the attributes in the entry and make any appropriate DN
// replacements
final Collection originalAttributes = e.getAttributes();
final ArrayList newAttributes =
new ArrayList<>(originalAttributes.size());
for (final Attribute a : originalAttributes)
{
final String[] originalValues = a.getValues();
final String[] newValues = new String[originalValues.length];
for (int i=0; i < originalValues.length; i++)
{
newValues[i] = processString(originalValues[i]);
}
newAttributes.add(new Attribute(a.getName(), newValues));
}
return new Entry(processString(e.getDN()), newAttributes);
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public LDIFChangeRecord transformChangeRecord(
@NotNull final LDIFChangeRecord r)
{
if (r == null)
{
return null;
}
if (r instanceof LDIFAddChangeRecord)
{
// Just use the same processing as for an entry.
final LDIFAddChangeRecord addRecord = (LDIFAddChangeRecord) r;
return new LDIFAddChangeRecord(transformEntry(addRecord.getEntryToAdd()),
addRecord.getControls());
}
if (r instanceof LDIFDeleteChangeRecord)
{
return new LDIFDeleteChangeRecord(processString(r.getDN()),
r.getControls());
}
else if (r instanceof LDIFModifyChangeRecord)
{
final LDIFModifyChangeRecord modRecord = (LDIFModifyChangeRecord) r;
final Modification[] originalMods = modRecord.getModifications();
final Modification[] newMods = new Modification[originalMods.length];
for (int i=0; i < originalMods.length; i++)
{
final Modification m = originalMods[i];
if (m.hasValue())
{
final String[] originalValues = m.getValues();
final String[] newValues = new String[originalValues.length];
for (int j=0; j < originalValues.length; j++)
{
newValues[j] = processString(originalValues[j]);
}
newMods[i] = new Modification(m.getModificationType(),
m.getAttributeName(), newValues);
}
else
{
newMods[i] = originalMods[i];
}
}
return new LDIFModifyChangeRecord(processString(modRecord.getDN()),
newMods, modRecord.getControls());
}
else if (r instanceof LDIFModifyDNChangeRecord)
{
final LDIFModifyDNChangeRecord modDNRecord = (LDIFModifyDNChangeRecord) r;
return new LDIFModifyDNChangeRecord(processString(modDNRecord.getDN()),
modDNRecord.getNewRDN(), modDNRecord.deleteOldRDN(),
processString(modDNRecord.getNewSuperiorDN()),
modDNRecord.getControls());
}
else
{
// This should never happen.
return r;
}
}
/**
* Identifies whether the provided string represents a DN that is at or below
* the specified source base DN. If so, then it will be updated to replace
* the old base DN with the new base DN. Otherwise, the original string will
* be returned.
*
* @param s The string to process.
*
* @return A new string if the provided value was a valid DN at or below the
* source DN, or the original string if it was not a valid DN or was
* not below the source DN.
*/
@Nullable()
String processString(@Nullable final String s)
{
if (s == null)
{
return null;
}
try
{
final DN dn = new DN(s);
if (! dn.isDescendantOf(sourceDN, true))
{
return s;
}
final RDN[] originalRDNs = dn.getRDNs();
final RDN[] sourceRDNs = sourceDN.getRDNs();
final ArrayList newRDNs = new ArrayList<>(2*originalRDNs.length);
final int numComponentsToKeep = originalRDNs.length - sourceRDNs.length;
for (int i=0; i < numComponentsToKeep; i++)
{
newRDNs.add(originalRDNs[i]);
}
newRDNs.addAll(targetRDNs);
return new DN(newRDNs).toString();
}
catch (final Exception e)
{
// This is fine. The value isn't a DN.
return s;
}
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public Entry translate(@NotNull final Entry original,
final long firstLineNumber)
{
return transformEntry(original);
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public LDIFChangeRecord translate(@NotNull final LDIFChangeRecord original,
final long firstLineNumber)
{
return transformChangeRecord(original);
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public Entry translateEntryToWrite(@NotNull final Entry original)
{
return transformEntry(original);
}
/**
* {@inheritDoc}
*/
@Override()
@Nullable()
public LDIFChangeRecord translateChangeRecordToWrite(
@NotNull final LDIFChangeRecord original)
{
return transformChangeRecord(original);
}
}