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.HasSubordinatesVirtualAttributeCfg; 036 import org.opends.server.api.VirtualAttributeProvider; 037 import org.opends.server.api.Backend; 038 import org.opends.server.core.DirectoryServer; 039 import org.opends.server.core.SearchOperation; 040 import org.opends.server.config.ConfigException; 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 X.501. 062 */ 063 public class HasSubordinatesVirtualAttributeProvider 064 extends VirtualAttributeProvider<HasSubordinatesVirtualAttributeCfg> 065 { 066 /** 067 * The tracer object for the debug logger. 068 */ 069 private static final DebugTracer TRACER = getTracer(); 070 071 /** 072 * Creates a new instance of this HasSubordinates virtual attribute provider. 073 */ 074 public HasSubordinatesVirtualAttributeProvider() 075 { 076 super(); 077 078 // All initialization should be performed in the 079 // initializeVirtualAttributeProvider method. 080 } 081 082 083 084 /** 085 * {@inheritDoc} 086 */ 087 @Override() 088 public void initializeVirtualAttributeProvider( 089 HasSubordinatesVirtualAttributeCfg configuration) 090 throws ConfigException, InitializationException 091 { 092 // No initialization is required. 093 } 094 095 096 097 /** 098 * {@inheritDoc} 099 */ 100 @Override() 101 public boolean isMultiValued() 102 { 103 return false; 104 } 105 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override() 112 public LinkedHashSet<AttributeValue> getValues(Entry entry, 113 VirtualAttributeRule rule) 114 { 115 LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); 116 117 Backend backend = DirectoryServer.getBackend(entry.getDN()); 118 119 try 120 { 121 ConditionResult ret = backend.hasSubordinates(entry.getDN()); 122 if(ret != null && ret != ConditionResult.UNDEFINED) 123 { 124 AttributeValue value = 125 new AttributeValue(ByteStringFactory.create(ret.toString()), 126 ByteStringFactory.create(ret.toString())); 127 values.add(value); 128 } 129 } 130 catch(DirectoryException de) 131 { 132 if (debugEnabled()) 133 { 134 TRACER.debugCaught(DebugLogLevel.ERROR, de); 135 } 136 } 137 138 return values; 139 } 140 141 142 143 /** 144 * {@inheritDoc} 145 */ 146 @Override() 147 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 148 { 149 Backend backend = DirectoryServer.getBackend(entry.getDN()); 150 151 try 152 { 153 ConditionResult ret = backend.hasSubordinates(entry.getDN()); 154 return ret != null && ret != ConditionResult.UNDEFINED; 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 ConditionResult ret = backend.hasSubordinates(entry.getDN()); 181 if(ret != null && ret != ConditionResult.UNDEFINED) 182 { 183 return ConditionResult.valueOf(value.getNormalizedStringValue()). 184 equals(ret); 185 } 186 return false; 187 } 188 catch(DirectoryException de) 189 { 190 if (debugEnabled()) 191 { 192 TRACER.debugCaught(DebugLogLevel.ERROR, de); 193 } 194 195 return false; 196 } 197 } 198 199 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override() 205 public ConditionResult matchesSubstring(Entry entry, 206 VirtualAttributeRule rule, 207 ByteString subInitial, 208 List<ByteString> subAny, 209 ByteString subFinal) 210 { 211 // This virtual attribute does not support substring matching. 212 return ConditionResult.UNDEFINED; 213 } 214 215 216 217 /** 218 * {@inheritDoc} 219 */ 220 @Override() 221 public ConditionResult greaterThanOrEqualTo(Entry entry, 222 VirtualAttributeRule rule, 223 AttributeValue value) 224 { 225 // This virtual attribute does not support ordering matching. 226 return ConditionResult.UNDEFINED; 227 } 228 229 230 231 /** 232 * {@inheritDoc} 233 */ 234 @Override() 235 public ConditionResult lessThanOrEqualTo(Entry entry, 236 VirtualAttributeRule rule, 237 AttributeValue value) 238 { 239 // This virtual attribute does not support ordering matching. 240 return ConditionResult.UNDEFINED; 241 } 242 243 244 245 /** 246 * {@inheritDoc} 247 */ 248 @Override() 249 public ConditionResult approximatelyEqualTo(Entry entry, 250 VirtualAttributeRule rule, 251 AttributeValue value) 252 { 253 // This virtual attribute does not support approximate matching. 254 return ConditionResult.UNDEFINED; 255 } 256 257 258 259 /** 260 * {@inheritDoc}. This virtual attribute will support search operations only 261 * if one of the following is true about the search filter: 262 * <UL> 263 * <LI>It is an equality filter targeting the associated attribute 264 * type.</LI> 265 * <LI>It is an AND filter in which at least one of the components is an 266 * equality filter targeting the associated attribute type.</LI> 267 * <LI>It is an OR filter in which all of the components are equality 268 * filters targeting the associated attribute type.</LI> 269 * </UL> 270 */ 271 @Override() 272 public boolean isSearchable(VirtualAttributeRule rule, 273 SearchOperation searchOperation) 274 { 275 return false; 276 } 277 278 279 280 /** 281 * {@inheritDoc} 282 */ 283 @Override() 284 public void processSearch(VirtualAttributeRule rule, 285 SearchOperation searchOperation) 286 { 287 searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); 288 289 Message message = ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE.get( 290 rule.getAttributeType().getNameOrOID()); 291 searchOperation.appendErrorMessage(message); 292 } 293 } 294