下面列出了javax.naming.directory.DirContext#ADD_ATTRIBUTE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void testGetCompensatingModificationItem_AddExistingAttribute()
throws NamingException {
BasicAttribute attribute = new BasicAttribute("someattr");
attribute.add("value1");
attribute.add("value2");
Attributes attributes = new BasicAttributes();
attributes.put(attribute);
BasicAttribute modificationAttribute = new BasicAttribute("someattr");
modificationAttribute.add("newvalue1");
modificationAttribute.add("newvalue2");
ModificationItem originalItem = new ModificationItem(
DirContext.ADD_ATTRIBUTE, new BasicAttribute("someattr"));
// Perform test
ModificationItem result = tested.getCompensatingModificationItem(
attributes, originalItem);
// Verify result
assertThat(result.getModificationOp()).isEqualTo(DirContext.REPLACE_ATTRIBUTE);
Attribute resultAttribute = result.getAttribute();
assertThat(resultAttribute.getID()).isEqualTo("someattr");
assertThat(result.getAttribute().get(0)).isEqualTo("value1");
assertThat(result.getAttribute().get(1)).isEqualTo("value2");
}
@Test
public void testModifyAttributes_MultiValueAdd() {
BasicAttribute attr = new BasicAttribute("description", "Some other description");
attr.add("Another description");
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr);
tested.modifyAttributes(PERSON4_DN, mods);
DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN);
List<String> attributes = Arrays.asList(result.getStringAttributes("description"));
assertThat(attributes).hasSize(3);
assertThat(attributes.contains("Some other description")).isTrue();
assertThat(attributes.contains("Another description")).isTrue();
assertThat(attributes.contains("Some description")).isTrue();
}
/**
* Test written originally to verify that duplicates are allowed on ordered
* attributes, but had to be changed since Apache DS seems to disallow
* duplicates even for ordered attributes.
*/
@Test
public void testModifyAttributes_MultiValueAddDuplicateToOrdered() {
BasicAttribute attr = new BasicAttribute("description", "Some other description", true); // ordered
attr.add("Another description");
// Commented out duplicate to make test work for Apache DS
// attr.add("Some description");
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr);
tested.modifyAttributes(PERSON4_DN, mods);
DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN);
List<String> attributes = Arrays.asList(result.getStringAttributes("description"));
assertThat(attributes).hasSize(3);
assertThat(attributes.contains("Some other description")).isTrue();
assertThat(attributes.contains("Another description")).isTrue();
assertThat(attributes.contains("Some description")).isTrue();
}
@Test
public void testGetCompensatingModificationItem_AddNonExistingAttribute()
throws NamingException {
Attributes attributes = new BasicAttributes();
BasicAttribute modificationAttribute = new BasicAttribute("someattr");
modificationAttribute.add("newvalue1");
modificationAttribute.add("newvalue2");
ModificationItem originalItem = new ModificationItem(
DirContext.ADD_ATTRIBUTE, modificationAttribute);
// Perform test
ModificationItem result = tested.getCompensatingModificationItem(
attributes, originalItem);
// Verify result
assertThat(result.getModificationOp()).isEqualTo(DirContext.REMOVE_ATTRIBUTE);
Attribute resultAttribute = result.getAttribute();
assertThat(resultAttribute.getID()).isEqualTo("someattr");
assertThat(resultAttribute.size()).isEqualTo(0);
}
/**
* Convert a ModificationItem to an instance of a ServerModification object
*
* @param modificationImpl the modification instance to convert
* @param attributeType the associated attributeType
* @return a instance of a ServerModification object
*/
private static Modification toServerModification( ModificationItem modificationImpl, AttributeType attributeType )
throws LdapException
{
ModificationOperation operation;
switch ( modificationImpl.getModificationOp() )
{
case DirContext.REMOVE_ATTRIBUTE:
operation = ModificationOperation.REMOVE_ATTRIBUTE;
break;
case DirContext.REPLACE_ATTRIBUTE:
operation = ModificationOperation.REPLACE_ATTRIBUTE;
break;
case DirContext.ADD_ATTRIBUTE:
default:
operation = ModificationOperation.ADD_ATTRIBUTE;
break;
}
Modification modification = new DefaultModification(
operation,
ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) );
return modification;
}
/**
* Convert a ModificationItem to an instance of a ServerModification object
*
* @param modificationImpl the modification instance to convert
* @param attributeType the associated attributeType
* @return a instance of a ServerModification object
*/
private static Modification toServerModification( ModificationItem modificationImpl, AttributeType attributeType )
throws LdapException
{
ModificationOperation operation;
switch ( modificationImpl.getModificationOp() )
{
case DirContext.REMOVE_ATTRIBUTE:
operation = ModificationOperation.REMOVE_ATTRIBUTE;
break;
case DirContext.REPLACE_ATTRIBUTE:
operation = ModificationOperation.REPLACE_ATTRIBUTE;
break;
case DirContext.ADD_ATTRIBUTE:
default:
operation = ModificationOperation.ADD_ATTRIBUTE;
break;
}
Modification modification = new DefaultModification(
operation,
ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) );
return modification;
}
@Override
public boolean addMember(GroupMember groupMember) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
Groups group =new Groups();
group.setName(groupMember.getGroupName());
create(group);
}
String uniqueMember="uid="+groupMember.getMemberName()+",dc=users,"+ldapUtils.getBaseDN();
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("uniqueMember",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",dc=groups,"+ldapUtils.getBaseDN();
logger.debug("dn : "+dn);
logger.debug("uniqueMember : "+uniqueMember);
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@LdapOperation
@ModifyOperation
public final void replaceStringAttribute( final String entryDN, final String attributeName, final String oldValue, final String newValue )
throws ChaiUnavailableException, ChaiOperationException
{
activityPreCheck();
getInputValidator().replaceStringAttribute( entryDN, attributeName, oldValue, newValue );
// Create the ModificationItem
final ModificationItem[] mods = new ModificationItem[2];
// Mark the flag to remover the existing attribute.
mods[0] = new ModificationItem( DirContext.REMOVE_ATTRIBUTE, new BasicAttribute( attributeName, oldValue ) );
// Mark the flag to add the new attribute
mods[1] = new ModificationItem( DirContext.ADD_ATTRIBUTE, new BasicAttribute( attributeName, newValue ) );
// get ldap connection
final LdapContext ldapConnection = getLdapConnection();
// Modify the Attributes.
try
{
ldapConnection.modifyAttributes( addJndiEscape( entryDN ), mods );
}
catch ( NamingException e )
{
convertNamingException( e );
}
}
public void assignUser(String username, String groupName) throws NamingException {
try {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod = new BasicAttribute("member", getUserDN(username));
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod);
context.modifyAttributes(getGroupDN(groupName), mods);
} catch (AttributeInUseException e) {
// If user is already added, ignore exception
}
}
public void modify() throws AttributeModificationException, NamingException{
//Get a reference to a directory context
int modType;
// decode the modification type to one which the context will understand
switch (modifyType){
case ldapConnection.MODIFY_REPLACE: // attributes require name=value pairs
modType = DirContext.REPLACE_ATTRIBUTE;
break;
case ldapConnection.MODIFY_ADD:
modType = DirContext.ADD_ATTRIBUTE; // attributes require name=value pairs
break;
case ldapConnection.MODIFY_DELETE:
modType = DirContext.REMOVE_ATTRIBUTE; // attributes require names only
break;
default:
modType = DirContext.REPLACE_ATTRIBUTE;
}// switch
DirContext ctx = new InitialDirContext(env);
Attributes attributes = processAttributes();
ctx.modifyAttributes(dn, modType, attributes);
ctx.close();
}
private String performOperationChangeUnicodePwd(String entryName, IPipeLineSession session, Map paramValueMap) throws SenderException, ParameterException {
ModificationItem[] modificationItems = new ModificationItem[2];
modificationItems[0] = new ModificationItem(
DirContext.REMOVE_ATTRIBUTE,
new BasicAttribute("unicodePwd", encodeUnicodePwd(paramValueMap.get("oldPassword"))));
modificationItems[1] = new ModificationItem(
DirContext.ADD_ATTRIBUTE,
new BasicAttribute("unicodePwd", encodeUnicodePwd(paramValueMap.get("newPassword"))));
DirContext dirContext = null;
try{
dirContext = getDirContext(paramValueMap);
dirContext.modifyAttributes(entryName, modificationItems);
return DEFAULT_RESULT_CHANGE_UNICODE_PWD_OK;
} catch(NamingException e) {
// https://wiki.servicenow.com/index.php?title=LDAP_Error_Codes:
// 19 LDAP_CONSTRAINT_VIOLATION Indicates that the attribute value specified in a modify, add, or modify DN operation violates constraints placed on the attribute. The constraint can be one of size or content (string only, no binary).
// AD:
// [LDAP: error code 19 - 0000052D: AtrErr: DSID-03191041, #1...
if(e.getMessage().startsWith("[LDAP: error code 19 - ") ) {
if (log.isDebugEnabled()) log.debug("Operation [" + getOperation()+ "] old password doesn't match or new password doesn't comply with policy for: " + entryName);
return DEFAULT_RESULT_CHANGE_UNICODE_PWD_NOK;
} else {
storeLdapException(e, session);
throw new SenderException("Exception in operation [" + getOperation()+ "] entryName ["+entryName+"]", e);
}
} finally {
closeDirContext(dirContext);
}
}
@Test
public void testModifyAttributes_MultiValueAddDuplicateToUnordered() {
BasicAttribute attr = new BasicAttribute("description", "Some description");
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr);
try {
tested.modifyAttributes(PERSON4_DN, mods);
fail("AttributeInUseException expected");
}
catch (AttributeInUseException expected) {
// expected
}
}
@Override
public boolean addMember(GroupMember groupMember) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
Groups group =new Groups();
group.setName(groupMember.getGroupName());
return create(group);
}
String uniqueMember="";
SearchControls memberSearchControls = new SearchControls();
logger.debug("user Search : "+"(sAMAccountName="+groupMember.getMemberName()+")");
memberSearchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> memberResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+groupMember.getMemberName()+")", memberSearchControls);
if (memberResults == null || !memberResults.hasMore()) {
}else{
SearchResult memberSr = (SearchResult) memberResults.next();
uniqueMember =memberSr.getNameInNamespace();
logger.debug("uniqueMember : "+uniqueMember);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("member",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",cn=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
public final void writeStringAttributes(
final String entryDN,
final Map<String, String> attributeValueProps,
final boolean overwrite,
final BasicControl[] controls
)
throws ChaiUnavailableException, ChaiOperationException
{
activityPreCheck();
getInputValidator().writeStringAttributes( entryDN, attributeValueProps, overwrite );
// Determine the modification type, if replace, only replace on the first attribute, the rest just get added.
final int modType = overwrite ? DirContext.REPLACE_ATTRIBUTE : DirContext.ADD_ATTRIBUTE;
// Create the ModificationItem
final List<ModificationItem> modificationItems = new ArrayList<>();
for ( final Map.Entry<String, String> entry : attributeValueProps.entrySet() )
{
// Create a BasicAttribute for the object.
final BasicAttribute attributeToReplace = new BasicAttribute( entry.getKey(), entry.getValue() );
// Populate the ModificationItem object with the flag & the attribute to replace.
modificationItems.add( new ModificationItem( modType, attributeToReplace ) );
}
// convert to array
final ModificationItem[] modificationItemArray = modificationItems.toArray( new ModificationItem[modificationItems.size()] );
// get ldap connection
final LdapContext ldapConnection = getLdapConnection();
// Modify the Attributes.
try
{
ldapConnection.modifyAttributes( addJndiEscape( entryDN ), modificationItemArray );
}
catch ( NamingException e )
{
convertNamingException( e );
}
}
/**
* Parse a modify change type.
* <p/>
* The grammar is : <changerecord> ::= "changetype:" FILL "modify" SEP
* <mod-spec> <mod-specs-e> <mod-spec> ::= "add:" <mod-val> | "delete:"
* <mod-val-del> | "replace:" <mod-val> <mod-specs-e> ::= <mod-spec>
* <mod-specs-e> | e <mod-val> ::= FILL ATTRIBUTE-DESCRIPTION SEP
* ATTRVAL-SPEC <attrval-specs-e> "-" SEP <mod-val-del> ::= FILL
* ATTRIBUTE-DESCRIPTION SEP <attrval-specs-e> "-" SEP <attrval-specs-e> ::=
* ATTRVAL-SPEC <attrval-specs> | e *
*
* @param entry The entry to feed
* @param iter The lines
*/
private void parseModify(Entry entry, Iterator iter) {
int state = MOD_SPEC;
String modified = null;
int modification = 0;
// The following flag is used to deal with empty modifications
boolean isEmptyValue = true;
while (iter.hasNext()) {
String line = (String) iter.next();
String lowerLine = line.toLowerCase();
if (lowerLine.startsWith("-")) {
if (state != ATTRVAL_SPEC_OR_SEP) {
throw new LdifParseException("Bad modify separator", line);
} else {
if (isEmptyValue) {
// Update the entry
entry.addModificationItem(modification, modified, null);
}
state = MOD_SPEC;
isEmptyValue = true;
continue;
}
} else if (lowerLine.startsWith("add:")) {
if ((state != MOD_SPEC) && (state != ATTRVAL_SPEC)) {
throw new LdifParseException("Bad modify state", line);
}
modified = line.substring("add:".length()).trim();
modification = DirContext.ADD_ATTRIBUTE;
state = ATTRVAL_SPEC;
} else if (lowerLine.startsWith("delete:")) {
if ((state != MOD_SPEC) && (state != ATTRVAL_SPEC)) {
throw new LdifParseException("Bad modify state", line);
}
modified = line.substring("delete:".length()).trim();
modification = DirContext.REMOVE_ATTRIBUTE;
state = ATTRVAL_SPEC_OR_SEP;
} else if (lowerLine.startsWith("replace:")) {
if ((state != MOD_SPEC) && (state != ATTRVAL_SPEC)) {
throw new LdifParseException("Bad modify state", line);
}
modified = line.substring("replace:".length()).trim();
modification = DirContext.REPLACE_ATTRIBUTE;
state = ATTRVAL_SPEC_OR_SEP;
} else {
if ((state != ATTRVAL_SPEC) && (state != ATTRVAL_SPEC_OR_SEP)) {
throw new LdifParseException("Bad modify state", line);
}
// A standard AttributeType/AttributeValue pair
int colonIndex = line.indexOf(':');
String attributeType = line.substring(0, colonIndex);
if (!attributeType.equals(modified)) {
throw new LdifParseException("Bad modify attribute", line);
}
// We should *not* have a DN twice
if (attributeType.equals("dn")) {
throw new LdifParseException("A ldif entry should not have two DN", line);
}
Object attributeValue = parseValue(line, colonIndex);
// Update the entry
entry.addModificationItem(modification, attributeType, attributeValue);
isEmptyValue = false;
state = ATTRVAL_SPEC_OR_SEP;
}
}
}
/**
* Dumps the modifications
*/
private String dumpModificationItems()
{
StringBuffer sb = new StringBuffer();
for (ModificationItem modif : modificationList) {
sb.append(" Operation: ");
switch (modif.getModificationOp()) {
case DirContext.ADD_ATTRIBUTE :
sb.append("ADD\n");
break;
case DirContext.REMOVE_ATTRIBUTE :
sb.append("REMOVE\n");
break;
case DirContext.REPLACE_ATTRIBUTE :
sb.append("REPLACE \n");
break;
}
Attribute attribute = modif.getAttribute();
sb.append(" Attribute: ").append(attribute.getID()).append('\n');
if (attribute.size() != 0) {
try {
for (NamingEnumeration values = attribute.getAll(); values.hasMoreElements();) {
Object value = values.nextElement();
if (value instanceof String) {
sb.append(" ").append((String) value).append('\n');
} else {
sb.append(" ").append(Utils.dumpBytes((byte[]) value)).append('\n');
}
}
}
catch (NamingException ne) {
return "";
}
}
}
return sb.toString();
}
protected void modifyAddEntry(final List<ModificationItem> modifyList, final String name, final String value) {
final Attribute attr = new BasicAttribute(name, value);
final ModificationItem mod = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr);
modifyList.add(mod);
}
/**
* Get a ModificationItem to use for rollback of the supplied modification.
*
* @param originalAttributes
* All Attributes of the target DN that are affected of any of
* the ModificationItems.
* @param modificationItem
* the ModificationItem to create a rollback item for.
* @return A ModificationItem to use for rollback of the supplied
* ModificationItem.
*/
protected ModificationItem getCompensatingModificationItem(
Attributes originalAttributes, ModificationItem modificationItem) {
Attribute modificationAttribute = modificationItem.getAttribute();
Attribute originalAttribute = originalAttributes
.get(modificationAttribute.getID());
if (modificationItem.getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
if (modificationAttribute.size() == 0) {
// If the modification attribute size it means that the
// Attribute should be removed entirely - we should store a
// ModificationItem to restore all present values for rollback.
return new ModificationItem(DirContext.ADD_ATTRIBUTE,
(Attribute) originalAttribute.clone());
} else {
// The rollback modification will be to re-add the removed
// attribute values.
return new ModificationItem(DirContext.ADD_ATTRIBUTE,
(Attribute) modificationAttribute.clone());
}
} else if (modificationItem.getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
if (originalAttribute != null) {
return new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
(Attribute) originalAttribute.clone());
} else {
// The attribute doesn't previously exist - the rollback
// operation will be to remove the attribute.
return new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
new BasicAttribute(modificationAttribute.getID()));
}
} else {
// An ADD_ATTRIBUTE operation
if (originalAttribute == null) {
// The attribute doesn't previously exist - the rollback
// operation will be to remove the attribute.
return new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
new BasicAttribute(modificationAttribute.getID()));
} else {
// The attribute does exist before - we should store the
// previous value and it should be used for replacing in
// rollback.
return new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
(Attribute) originalAttribute.clone());
}
}
}
@Test
public void testRecordOperation() {
final ModificationItem incomingItem = new ModificationItem(
DirContext.ADD_ATTRIBUTE, new BasicAttribute("attribute1"));
ModificationItem[] incomingMods = new ModificationItem[]{incomingItem};
final ModificationItem compensatingItem = new ModificationItem(
DirContext.ADD_ATTRIBUTE, new BasicAttribute("attribute2"));
final Attributes expectedAttributes = new BasicAttributes();
tested = new ModifyAttributesOperationRecorder(ldapOperationsMock) {
IncrementalAttributesMapper getAttributesMapper(String[] attributeNames) {
return attributesMapperMock;
}
protected ModificationItem getCompensatingModificationItem(
Attributes originalAttributes,
ModificationItem modificationItem) {
assertThat(originalAttributes).isSameAs(expectedAttributes);
assertThat(modificationItem).isSameAs(incomingItem);
return compensatingItem;
}
};
LdapName expectedName = LdapUtils.newLdapName("cn=john doe");
when(attributesMapperMock.hasMore()).thenReturn(true, false);
when(attributesMapperMock.getAttributesForLookup())
.thenReturn(new String[]{"attribute1"});
when(ldapOperationsMock.lookup(expectedName, new String[]{"attribute1"}, attributesMapperMock))
.thenReturn(expectedAttributes);
when(attributesMapperMock.getCollectedAttributes())
.thenReturn(expectedAttributes);
// Perform test
CompensatingTransactionOperationExecutor operation = tested
.recordOperation(new Object[]{expectedName, incomingMods});
// Verify outcome
assertThat(operation instanceof ModifyAttributesOperationExecutor).isTrue();
ModifyAttributesOperationExecutor rollbackOperation = (ModifyAttributesOperationExecutor) operation;
assertThat(rollbackOperation.getDn()).isSameAs(expectedName);
assertThat(rollbackOperation.getLdapOperations()).isSameAs(ldapOperationsMock);
ModificationItem[] actualModifications = rollbackOperation.getActualModifications();
assertThat(actualModifications.length).isEqualTo(incomingMods.length);
assertThat(actualModifications[0]).isEqualTo(incomingMods[0]);
assertThat(rollbackOperation.getCompensatingModifications().length).isEqualTo(1);
assertThat(rollbackOperation.getCompensatingModifications()[0]).isSameAs(compensatingItem);
}
/**
* <p>
* Adds the given {@link Attribute} instance using the given DN. This method performs a ADD_ATTRIBUTE operation.
* </p>
*
* @param dn
* @param attribute
*/
public void addAttribute(String dn, Attribute attribute) {
ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute)};
modifyAttributes(dn, mods, null);
}