001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.extensions; 018 019import java.util.List; 020 021import org.forgerock.i18n.LocalizableMessage; 022import org.forgerock.i18n.slf4j.LocalizedLogger; 023import org.forgerock.opendj.config.server.ConfigException; 024import org.forgerock.opendj.ldap.ByteString; 025import org.forgerock.opendj.ldap.ConditionResult; 026import org.forgerock.opendj.ldap.ResultCode; 027import org.forgerock.opendj.config.server.ConfigurationChangeListener; 028import org.forgerock.opendj.server.config.server.MemberVirtualAttributeCfg; 029import org.opends.server.api.Group; 030import org.opends.server.api.VirtualAttributeProvider; 031import org.opends.server.core.DirectoryServer; 032import org.opends.server.types.Attribute; 033import org.opends.server.types.AttributeBuilder; 034import org.opends.server.types.Attributes; 035import org.opends.server.core.SearchOperation; 036import org.forgerock.opendj.config.server.ConfigChangeResult; 037import org.forgerock.opendj.ldap.DN; 038import org.opends.server.types.Entry; 039import org.opends.server.types.InitializationException; 040import org.opends.server.types.MemberList; 041import org.opends.server.types.MembershipException; 042import org.opends.server.types.VirtualAttributeRule; 043 044/** 045 * This class implements a virtual attribute provider that works in conjunction 046 * with virtual static groups to generate the values for the member or 047 * uniqueMember attribute. 048 */ 049public class MemberVirtualAttributeProvider 050 extends VirtualAttributeProvider<MemberVirtualAttributeCfg> 051 implements ConfigurationChangeListener<MemberVirtualAttributeCfg> 052{ 053 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 054 055 /** The current configuration for this member virtual attribute. */ 056 private MemberVirtualAttributeCfg currentConfig; 057 058 /** Creates a new instance of this member virtual attribute provider. */ 059 public MemberVirtualAttributeProvider() 060 { 061 super(); 062 063 // All initialization should be performed in the 064 // initializeVirtualAttributeProvider method. 065 } 066 067 @Override 068 public void initializeVirtualAttributeProvider( 069 MemberVirtualAttributeCfg configuration) 070 throws ConfigException, InitializationException 071 { 072 configuration.addMemberChangeListener(this); 073 currentConfig = configuration; 074 } 075 076 @Override 077 public boolean isMultiValued() 078 { 079 return true; 080 } 081 082 @Override 083 public Attribute getValues(Entry entry, VirtualAttributeRule rule) 084 { 085 if (! currentConfig.isAllowRetrievingMembership()) 086 { 087 return Attributes.empty(rule.getAttributeType()); 088 } 089 090 Group<?> g = 091 DirectoryServer.getGroupManager().getGroupInstance(entry.getName()); 092 if (g == null) 093 { 094 return Attributes.empty(rule.getAttributeType()); 095 } 096 097 AttributeBuilder builder = new AttributeBuilder(rule.getAttributeType()); 098 try 099 { 100 MemberList memberList = g.getMembers(); 101 while (memberList.hasMoreMembers()) 102 { 103 try 104 { 105 DN memberDN = memberList.nextMemberDN(); 106 if (memberDN != null) 107 { 108 builder.add(ByteString.valueOfUtf8(memberDN.toString())); 109 } 110 } 111 catch (MembershipException me) 112 { 113 if (! me.continueIterating()) 114 { 115 break; 116 } 117 } 118 } 119 } 120 catch (Exception e) 121 { 122 logger.traceException(e); 123 } 124 125 return builder.toAttribute(); 126 } 127 128 @Override 129 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 130 { 131 Group<?> g = 132 DirectoryServer.getGroupManager().getGroupInstance(entry.getName()); 133 if (g == null) 134 { 135 return false; 136 } 137 138 try 139 { 140 MemberList memberList = g.getMembers(); 141 while (memberList.hasMoreMembers()) 142 { 143 try 144 { 145 DN memberDN = memberList.nextMemberDN(); 146 if (memberDN != null) 147 { 148 memberList.close(); 149 return true; 150 } 151 } 152 catch (MembershipException me) 153 { 154 if (! me.continueIterating()) 155 { 156 break; 157 } 158 } 159 } 160 } 161 catch (Exception e) 162 { 163 logger.traceException(e); 164 } 165 166 return false; 167 } 168 169 @Override 170 public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value) 171 { 172 Group<?> g = 173 DirectoryServer.getGroupManager().getGroupInstance(entry.getName()); 174 if (g == null) 175 { 176 return false; 177 } 178 179 try 180 { 181 return g.isMember(DN.valueOf(value)); 182 } 183 catch (Exception e) 184 { 185 logger.traceException(e); 186 } 187 188 return false; 189 } 190 191 @Override 192 public ConditionResult matchesEqualityAssertion(Entry entry, 193 VirtualAttributeRule rule, ByteString assertionValue) 194 { 195 return ConditionResult.valueOf(hasValue(entry, rule, assertionValue)); 196 } 197 198 @Override 199 public ConditionResult matchesSubstring(Entry entry, 200 VirtualAttributeRule rule, 201 ByteString subInitial, 202 List<ByteString> subAny, 203 ByteString subFinal) 204 { 205 // DNs cannot be used in substring matching. 206 return ConditionResult.UNDEFINED; 207 } 208 209 @Override 210 public ConditionResult greaterThanOrEqualTo(Entry entry, 211 VirtualAttributeRule rule, 212 ByteString value) 213 { 214 // DNs cannot be used in ordering matching. 215 return ConditionResult.UNDEFINED; 216 } 217 218 @Override 219 public ConditionResult lessThanOrEqualTo(Entry entry, 220 VirtualAttributeRule rule, 221 ByteString value) 222 { 223 // DNs cannot be used in ordering matching. 224 return ConditionResult.UNDEFINED; 225 } 226 227 @Override 228 public ConditionResult approximatelyEqualTo(Entry entry, 229 VirtualAttributeRule rule, 230 ByteString value) 231 { 232 // DNs cannot be used in approximate matching. 233 return ConditionResult.UNDEFINED; 234 } 235 236 @Override 237 public boolean isSearchable(VirtualAttributeRule rule, 238 SearchOperation searchOperation, 239 boolean isPreIndexed) 240 { 241 return false; 242 } 243 244 @Override 245 public void processSearch(VirtualAttributeRule rule, 246 SearchOperation searchOperation) 247 { 248 searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); 249 return; 250 } 251 252 @Override 253 public boolean isConfigurationChangeAcceptable( 254 MemberVirtualAttributeCfg configuration, 255 List<LocalizableMessage> unacceptableReasons) 256 { 257 // The new configuration should always be acceptable. 258 return true; 259 } 260 261 @Override 262 public ConfigChangeResult applyConfigurationChange( 263 MemberVirtualAttributeCfg configuration) 264 { 265 currentConfig = configuration; 266 return new ConfigChangeResult(); 267 } 268}