001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.extensions; 028 029 030 031 import java.util.LinkedHashSet; 032 import java.util.List; 033 034 import org.opends.messages.Message; 035 import org.opends.server.admin.std.server.NumSubordinatesVirtualAttributeCfg; 036 import org.opends.server.api.VirtualAttributeProvider; 037 import org.opends.server.api.Backend; 038 import org.opends.server.config.ConfigException; 039 import org.opends.server.core.DirectoryServer; 040 import org.opends.server.core.SearchOperation; 041 import org.opends.server.loggers.debug.DebugTracer; 042 import org.opends.server.types.AttributeValue; 043 import org.opends.server.types.ByteString; 044 import org.opends.server.types.ByteStringFactory; 045 import org.opends.server.types.ConditionResult; 046 import org.opends.server.types.DebugLogLevel; 047 import org.opends.server.types.DirectoryException; 048 import org.opends.server.types.Entry; 049 import org.opends.server.types.InitializationException; 050 import org.opends.server.types.ResultCode; 051 import org.opends.server.types.VirtualAttributeRule; 052 053 import static org.opends.messages.ExtensionMessages.*; 054 import static org.opends.server.loggers.debug.DebugLogger.getTracer; 055 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; 056 057 058 059 /** 060 * This class implements a virtual attribute provider that is meant to serve the 061 * hasSubordinates operational attribute as described in 062 * draft-ietf-boreham-numsubordinates. 063 */ 064 public class NumSubordinatesVirtualAttributeProvider 065 extends VirtualAttributeProvider<NumSubordinatesVirtualAttributeCfg> 066 { 067 /** 068 * The tracer object for the debug logger. 069 */ 070 private static final DebugTracer TRACER = getTracer(); 071 072 /** 073 * Creates a new instance of this NumSubordinates virtual attribute provider. 074 */ 075 public NumSubordinatesVirtualAttributeProvider() 076 { 077 super(); 078 079 // All initialization should be performed in the 080 // initializeVirtualAttributeProvider method. 081 } 082 083 084 085 /** 086 * {@inheritDoc} 087 */ 088 @Override() 089 public void initializeVirtualAttributeProvider( 090 NumSubordinatesVirtualAttributeCfg configuration) 091 throws ConfigException, InitializationException 092 { 093 // No initialization is required. 094 } 095 096 097 098 /** 099 * {@inheritDoc} 100 */ 101 @Override() 102 public boolean isMultiValued() 103 { 104 return false; 105 } 106 107 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override() 113 public LinkedHashSet<AttributeValue> getValues(Entry entry, 114 VirtualAttributeRule rule) 115 { 116 LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); 117 118 Backend backend = DirectoryServer.getBackend(entry.getDN()); 119 120 try 121 { 122 long count = backend.numSubordinates(entry.getDN(), false); 123 if(count >= 0) 124 { 125 AttributeValue value = 126 new AttributeValue(ByteStringFactory.create(String.valueOf(count)), 127 ByteStringFactory.create(String.valueOf(count))); 128 values.add(value); 129 } 130 } 131 catch(DirectoryException de) 132 { 133 if (debugEnabled()) 134 { 135 TRACER.debugCaught(DebugLogLevel.ERROR, de); 136 } 137 } 138 139 return values; 140 } 141 142 143 144 /** 145 * {@inheritDoc} 146 */ 147 @Override() 148 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 149 { 150 Backend backend = DirectoryServer.getBackend(entry.getDN()); 151 152 try 153 { 154 return backend.numSubordinates(entry.getDN(), false) >= 0; 155 } 156 catch(DirectoryException de) 157 { 158 if (debugEnabled()) 159 { 160 TRACER.debugCaught(DebugLogLevel.ERROR, de); 161 } 162 163 return false; 164 } 165 } 166 167 168 169 /** 170 * {@inheritDoc} 171 */ 172 @Override() 173 public boolean hasValue(Entry entry, VirtualAttributeRule rule, 174 AttributeValue value) 175 { 176 Backend backend = DirectoryServer.getBackend(entry.getDN()); 177 178 try 179 { 180 long count = backend.numSubordinates(entry.getDN(), false); 181 if(count >= 0) 182 { 183 return Long.parseLong(value.getNormalizedStringValue()) == count; 184 } 185 return false; 186 } 187 catch(DirectoryException de) 188 { 189 if (debugEnabled()) 190 { 191 TRACER.debugCaught(DebugLogLevel.ERROR, de); 192 } 193 194 return false; 195 } 196 } 197 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override() 204 public ConditionResult matchesSubstring(Entry entry, 205 VirtualAttributeRule rule, 206 ByteString subInitial, 207 List<ByteString> subAny, 208 ByteString subFinal) 209 { 210 // This virtual attribute does not support substring matching. 211 return ConditionResult.UNDEFINED; 212 } 213 214 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override() 220 public ConditionResult approximatelyEqualTo(Entry entry, 221 VirtualAttributeRule rule, 222 AttributeValue value) 223 { 224 // This virtual attribute does not support approximate matching. 225 return ConditionResult.UNDEFINED; 226 } 227 228 229 230 /** 231 * {@inheritDoc}. This virtual attribute will support search operations only 232 * if one of the following is true about the search filter: 233 * <UL> 234 * <LI>It is an equality filter targeting the associated attribute 235 * type.</LI> 236 * <LI>It is an AND filter in which at least one of the components is an 237 * equality filter targeting the associated attribute type.</LI> 238 * <LI>It is an OR filter in which all of the components are equality 239 * filters targeting the associated attribute type.</LI> 240 * </UL> 241 */ 242 @Override() 243 public boolean isSearchable(VirtualAttributeRule rule, 244 SearchOperation searchOperation) 245 { 246 return false; 247 } 248 249 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override() 255 public void processSearch(VirtualAttributeRule rule, 256 SearchOperation searchOperation) 257 { 258 searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); 259 260 Message message = ERR_NUMSUBORDINATES_VATTR_NOT_SEARCHABLE.get( 261 rule.getAttributeType().getNameOrOID()); 262 searchOperation.appendErrorMessage(message); 263 } 264 } 265