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