View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.server.core.shared;
22  
23  
24  import java.time.Duration;
25  
26  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
27  import org.apache.directory.api.ldap.model.name.Dn;
28  import org.apache.directory.api.ldap.model.schema.SchemaManager;
29  import org.apache.directory.server.core.api.DnFactory;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  import com.github.benmanes.caffeine.cache.Cache;
34  import com.github.benmanes.caffeine.cache.Caffeine;
35  
36  
37  /**
38   * The default Dn factory implementation.
39   *
40   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
41   */
42  public class DefaultDnFactory implements DnFactory
43  {
44      private static final Logger LOG = LoggerFactory.getLogger( DefaultDnFactory.class );
45  
46      /** The cache for DNs */
47      private Cache<String, Dn> dnCache;
48  
49      /** The schema manager */
50      private SchemaManager schemaManager;
51  
52      /** Flag to enable stats */
53      private boolean enableStats = false;
54  
55      // stat counters
56      private int hitCount = 0;
57      private int missCount = 0;
58  
59  
60      /**
61       * Instantiates a new default Dn factory.
62       *
63       * @param schemaManager The SchemaManager instance
64       * @param cacheSize The cache size used to store DNs
65       */
66      public DefaultDnFactory( SchemaManager schemaManager, int cacheSize )
67      {
68          this.schemaManager = schemaManager;
69          this.dnCache = Caffeine.newBuilder().maximumSize( cacheSize ).expireAfterAccess( Duration.ofMinutes( 10L ) )
70              .build();
71      }
72  
73  
74      /**
75       * {@inheritDoc}
76       */
77      @Override
78      public Dn create( String dn ) throws LdapInvalidDnException
79      {
80          if ( dn == null )
81          {
82              return null;
83          }
84  
85          if ( dn.trim().length() == 0 )
86          {
87              return Dn.ROOT_DSE;
88          }
89  
90          Dn cachedDn = null;
91  
92          // read the explanation at the above DN_CACHE variable declaration
93          // for the reason for performing this check
94          if ( dnCache != null )
95          {
96              cachedDn = dnCache.getIfPresent( dn );
97          }
98  
99          if ( cachedDn == null )
100         {
101             LOG.debug( "Dn {} not found in the cache, creating", dn );
102 
103             cachedDn = new Dn( schemaManager, dn );
104 
105             if ( dnCache != null )
106             {
107                 dnCache.put( dn, cachedDn );
108             }
109 
110             if ( enableStats )
111             {
112                 missCount++;
113             }
114         }
115         else
116         {
117             if ( enableStats )
118             {
119                 hitCount++;
120             }
121         }
122 
123         LOG.debug( "Dn {} found in the cache", dn );
124 
125         if ( enableStats )
126         {
127             LOG.debug( "Dn cache hit - {} , miss - {} and is normalized = {}", hitCount, missCount, cachedDn.isSchemaAware() );
128         }
129 
130         return cachedDn;
131     }
132 
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public Dn create( String... upRdns ) throws LdapInvalidDnException
139     {
140         StringBuilder sb = new StringBuilder();
141         boolean isFirst = true;
142         
143         for ( String s : upRdns )
144         {
145             if ( isFirst )
146             {
147                 isFirst = false;
148             }
149             else
150             {
151                 sb.append( ',' );
152             }
153             
154             sb.append( s );
155         }
156 
157         String dn = sb.toString();
158         
159         return create( dn );
160     }
161 
162 }