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