View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.schema.bootstrap;
18  
19  
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.Hashtable;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.naming.NamingException;
27  
28  import org.apache.ldap.server.schema.OidRegistry;
29  import org.apache.ldap.server.schema.OidRegistryMonitor;
30  import org.apache.ldap.server.schema.OidRegistryMonitorAdapter;
31  
32  
33  /***
34   * Default OID registry implementation used to resolve a schema object OID 
35   * to a name and vice-versa.
36   * 
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   * @version $Rev: 328545 $
39   */
40  public class BootstrapOidRegistry implements OidRegistry
41  { 
42      /*** Maps OID to a name or a list of names if more than one name exists */
43      private Hashtable byOid = new Hashtable();
44      /*** Maps several names to an OID */
45      private Hashtable byName = new Hashtable();
46      /*** Default OidRegistryMonitor */
47      private OidRegistryMonitor monitor = new OidRegistryMonitorAdapter();
48      
49      
50      /***
51       * @see org.apache.ldap.server.schema.OidRegistry#getOid(java.lang.String)
52       */
53      public String getOid( String name ) throws NamingException
54      {
55          if ( name == null )
56          {
57              throw new NamingException( "name should not be null" );
58          }
59          /* If name is an OID than we return it back since inherently the
60           * OID is another name for the object referred to by OID and the
61           * caller does not know that the argument is an OID String.
62           */
63          if ( Character.isDigit( name.charAt( 0 ) ) )
64          {
65              monitor.getOidWithOid( name );
66              return name;
67          }
68  
69          // If name is mapped to a OID already return OID
70          if ( byName.containsKey( name ) )
71          {
72              String oid = ( String ) byName.get( name );
73              monitor.oidResolved( name, oid );
74              return oid;
75          }
76  
77          /*
78           * As a last resort we check if name is not normalized and if the
79           * normalized version used as a key returns an OID.  If the normalized
80           * name works add the normalized name as a key with its OID to the
81           * byName lookup.  BTW these normalized versions of the key are not
82           * returned on a getNameSet.
83           */
84           String lowerCase = name.trim().toLowerCase();
85           if ( ! name.equals( lowerCase )
86              && byName.containsKey( lowerCase ) )
87           {
88               String oid = ( String ) byName.get( lowerCase );
89               monitor.oidResolved( name, lowerCase, oid );
90  
91               // We expect to see this version of the key again so we add it
92               byName.put( name, oid );
93               return oid;
94           }
95  
96           NamingException fault = new NamingException ( "OID for name '"
97                   + name + "' was not " + "found within the OID registry" );
98           monitor.oidResolutionFailed( name, fault );
99           throw fault;
100     }
101 
102 
103     /***
104      * @see org.apache.ldap.server.schema.OidRegistry#hasOid(java.lang.String)
105      */
106     public boolean hasOid( String name )
107     {
108         if ( this.byName.containsKey( name ) || this.byOid.containsKey( name ) )
109         {
110             return true;
111         }
112 
113         String normalized = name.toLowerCase();
114         return this.byName.containsKey( normalized ) || this.byOid.containsKey( normalized );
115     }
116 
117 
118     /***
119      * @see org.apache.ldap.server.schema.OidRegistry#getPrimaryName(java.lang.String)
120      */
121     public String getPrimaryName( String oid ) throws NamingException
122     {
123         Object value = byOid.get( oid );
124         
125         if ( null == value )
126         {
127             NamingException fault = new NamingException ( "OID '" + oid
128                     + "' was not found within the OID registry" );
129             monitor.oidDoesNotExist( oid, fault );
130             throw fault;
131         }
132         
133         if ( value instanceof String )
134         {
135             monitor.nameResolved( oid, ( String ) value );
136             return ( String ) value;
137         }
138         
139         String name = ( String ) ( ( List ) value ).get( 0 );
140         monitor.nameResolved( oid, name );
141         return name;
142     }
143 
144 
145     /***
146      * @see org.apache.ldap.server.schema.OidRegistry#getNameSet(java.lang.String)
147      */
148     public List getNameSet( String oid ) throws NamingException
149     {
150         Object value = byOid.get( oid );
151         
152         if ( null == value )
153         {
154             NamingException fault = new NamingException ( "OID '" + oid
155                     + "' was not found within the OID registry" );
156             monitor.oidDoesNotExist( oid, fault );
157             throw fault;
158         }
159         
160         if ( value instanceof String )
161         {
162             List list = Collections.singletonList( value );
163             monitor.namesResolved( oid, list );
164             return list;
165         }
166         
167         monitor.namesResolved( oid, ( List ) value );
168         return ( List ) value;
169     }
170 
171 
172     /***
173      * @see org.apache.ldap.server.schema.OidRegistry#list()
174      */
175     public Iterator list()
176     {
177         return Collections.unmodifiableSet( byOid.keySet() ).iterator();
178     }
179 
180 
181     /***
182      * @see org.apache.ldap.server.schema.OidRegistry#register(String, String)
183      */
184     public void register( String name, String oid )
185     {
186         if ( ! Character.isDigit( oid.charAt( 0 ) ) )
187         {
188             throw new RuntimeException( "Swap the parameter order: the oid " +
189                 "does not start with a digit!" );
190         }
191 
192         /*
193          * Add the entry for the given name as is and its lowercased version if
194          * the lower cased name is different from the given name name.  
195          */
196         String lowerCase = name.toLowerCase();
197         if ( ! lowerCase.equals( name ) )
198         {
199             byName.put( lowerCase, oid );
200         }
201         
202         // Put both the name and the oid as names
203         byName.put( name, oid );
204         byName.put( oid, oid );
205         
206         /*
207          * Update OID Map
208          * 
209          * 1). Check if we already have a value[s] stored
210          *      1a). Value is a single value and is a String
211          *          Replace value with list containing old and new values
212          *      1b). More than one value stored in a list
213          *          Add new value to the list
214          * 2). If we do not have a value then we just add it as a String
215          */
216         Object value;
217         if ( ! byOid.containsKey( oid ) )
218         {
219             value = name;
220         }
221         else 
222         {
223             ArrayList list;
224             value = byOid.get( oid );
225             
226             if ( value instanceof String )
227             {
228                 String existingName = ( String ) value;
229                 
230                 // if the existing name is already there we don't readd it
231                 if ( existingName.equalsIgnoreCase( name ) )
232                 {
233                     return;
234                 }
235                 
236                 list = new ArrayList();
237                 list.add( value );
238                 value = list;
239             }
240             else if ( value instanceof ArrayList )
241             {
242                 list = ( ArrayList ) value;
243                 
244                 for ( int ii = 0; ii < list.size(); ii++ )
245                 {
246                     // One form or another of the name already exists in list
247                     if ( ! name.equalsIgnoreCase( ( String ) list.get( ii ) ) )
248                     {
249                         return;
250                     }
251                 }
252                 
253                 list.add( name );
254             }
255         }
256 
257         byOid.put( oid, value );
258         monitor.registered( name, oid );
259     }
260     
261     
262     /***
263      * Gets the monitor.
264      * 
265      * @return the monitor
266      */
267     OidRegistryMonitor getMonitor()
268     {
269         return monitor;
270     }
271 
272     
273     /***
274      * Sets the monitor.
275      * 
276      * @param monitor monitor to set.
277      */
278     void setMonitor( OidRegistryMonitor monitor )
279     {
280         this.monitor = monitor;
281     }
282 }
283