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    import java.util.UUID;
034    
035    import org.opends.messages.Message;
036    import org.opends.server.admin.std.server.EntryUUIDVirtualAttributeCfg;
037    import org.opends.server.api.VirtualAttributeProvider;
038    import org.opends.server.config.ConfigException;
039    import org.opends.server.core.SearchOperation;
040    import org.opends.server.loggers.debug.DebugTracer;
041    import org.opends.server.types.AttributeValue;
042    import org.opends.server.types.ByteString;
043    import org.opends.server.types.ByteStringFactory;
044    import org.opends.server.types.ConditionResult;
045    import org.opends.server.types.DebugLogLevel;
046    import org.opends.server.types.Entry;
047    import org.opends.server.types.InitializationException;
048    import org.opends.server.types.ResultCode;
049    import org.opends.server.types.VirtualAttributeRule;
050    
051    import static org.opends.messages.ExtensionMessages.*;
052    import static org.opends.server.loggers.debug.DebugLogger.*;
053    import static org.opends.server.util.ServerConstants.*;
054    import static org.opends.server.util.StaticUtils.*;
055    
056    
057    
058    /**
059     * This class implements a virtual attribute provider that is meant to serve the
060     * entryUUID operational attribute as described in RFC 4530.  Note that this
061     * should only be used for entries used in conjuntion with data in private
062     * backends (e.g., those holding the configuration, schema, monitor, and root
063     * DSE entries).  Real user data should have entry UUID values generated at the
064     * time the entries are added or imported.
065     */
066    public class EntryUUIDVirtualAttributeProvider
067           extends VirtualAttributeProvider<EntryUUIDVirtualAttributeCfg>
068    {
069      /**
070       * The tracer object for the debug logger.
071       */
072      private static final DebugTracer TRACER = getTracer();
073    
074      /**
075       * Creates a new instance of this entryUUID virtual attribute provider.
076       */
077      public EntryUUIDVirtualAttributeProvider()
078      {
079        super();
080    
081        // All initialization should be performed in the
082        // initializeVirtualAttributeProvider method.
083      }
084    
085    
086    
087      /**
088       * {@inheritDoc}
089       */
090      @Override()
091      public void initializeVirtualAttributeProvider(
092                                EntryUUIDVirtualAttributeCfg configuration)
093             throws ConfigException, InitializationException
094      {
095        // No initialization is required.
096      }
097    
098    
099    
100      /**
101       * {@inheritDoc}
102       */
103      @Override()
104      public boolean isMultiValued()
105      {
106        return false;
107      }
108    
109    
110    
111      /**
112       * {@inheritDoc}
113       */
114      @Override()
115      public LinkedHashSet<AttributeValue> getValues(Entry entry,
116                                                     VirtualAttributeRule rule)
117      {
118        LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
119    
120        String normDNString = entry.getDN().toNormalizedString();
121        String uuidString =
122             UUID.nameUUIDFromBytes(getBytes(normDNString)).toString();
123        values.add(new AttributeValue(ByteStringFactory.create(uuidString),
124                                      ByteStringFactory.create(uuidString)));
125    
126        return values;
127      }
128    
129    
130    
131      /**
132       * {@inheritDoc}
133       */
134      @Override()
135      public boolean hasValue(Entry entry, VirtualAttributeRule rule)
136      {
137        // This virtual attribute provider will always generate a value.
138        return true;
139      }
140    
141    
142    
143      /**
144       * {@inheritDoc}
145       */
146      @Override()
147      public boolean hasValue(Entry entry, VirtualAttributeRule rule,
148                              AttributeValue value)
149      {
150        try
151        {
152          String normalizedDN = entry.getDN().toNormalizedString();
153          String uuidString =
154               UUID.nameUUIDFromBytes(getBytes(normalizedDN)).toString();
155    
156          String normalizedValue = value.getNormalizedStringValue();
157          return uuidString.equals(normalizedValue);
158        }
159        catch (Exception e)
160        {
161          if (debugEnabled())
162          {
163            TRACER.debugCaught(DebugLogLevel.ERROR, e);
164          }
165    
166          return false;
167        }
168      }
169    
170    
171    
172      /**
173       * {@inheritDoc}
174       */
175      @Override()
176      public ConditionResult matchesSubstring(Entry entry,
177                                              VirtualAttributeRule rule,
178                                              ByteString subInitial,
179                                              List<ByteString> subAny,
180                                              ByteString subFinal)
181      {
182        // DNs cannot be used in substring matching.
183        return ConditionResult.UNDEFINED;
184      }
185    
186    
187    
188      /**
189       * {@inheritDoc}
190       */
191      @Override()
192      public ConditionResult greaterThanOrEqualTo(Entry entry,
193                                  VirtualAttributeRule rule,
194                                  AttributeValue value)
195      {
196        // DNs cannot be used in ordering matching.
197        return ConditionResult.UNDEFINED;
198      }
199    
200    
201    
202      /**
203       * {@inheritDoc}
204       */
205      @Override()
206      public ConditionResult lessThanOrEqualTo(Entry entry,
207                                  VirtualAttributeRule rule,
208                                  AttributeValue value)
209      {
210        // DNs cannot be used in ordering 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        // DNs cannot be used in 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_ENTRYUUID_VATTR_NOT_SEARCHABLE.get(
261                rule.getAttributeType().getNameOrOID());
262        searchOperation.appendErrorMessage(message);
263      }
264    }
265