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: 264732 $
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         return this.byName.containsKey( name ) || this.byOid.containsKey( name );
109     }
110 
111 
112     /***
113      * @see org.apache.ldap.server.schema.OidRegistry#getPrimaryName(java.lang.String)
114      */
115     public String getPrimaryName( String oid ) throws NamingException
116     {
117         Object value = byOid.get( oid );
118         
119         if ( null == value )
120         {
121             NamingException fault = new NamingException ( "OID '" + oid
122                     + "' was not found within the OID registry" );
123             monitor.oidDoesNotExist( oid, fault );
124             throw fault;
125         }
126         
127         if ( value instanceof String )
128         {
129             monitor.nameResolved( oid, ( String ) value );
130             return ( String ) value;
131         }
132         
133         String name = ( String ) ( ( List ) value ).get( 0 );
134         monitor.nameResolved( oid, name );
135         return name;
136     }
137 
138 
139     /***
140      * @see org.apache.ldap.server.schema.OidRegistry#getNameSet(java.lang.String)
141      */
142     public List getNameSet( String oid ) throws NamingException
143     {
144         Object value = byOid.get( oid );
145         
146         if ( null == value )
147         {
148             NamingException fault = new NamingException ( "OID '" + oid
149                     + "' was not found within the OID registry" );
150             monitor.oidDoesNotExist( oid, fault );
151             throw fault;
152         }
153         
154         if ( value instanceof String )
155         {
156             List list = Collections.singletonList( value );
157             monitor.namesResolved( oid, list );
158             return list;
159         }
160         
161         monitor.namesResolved( oid, ( List ) value );
162         return ( List ) value;
163     }
164 
165 
166     /***
167      * @see org.apache.ldap.server.schema.OidRegistry#list()
168      */
169     public Iterator list()
170     {
171         return Collections.unmodifiableSet( byOid.keySet() ).iterator();
172     }
173 
174 
175     /***
176      * @see org.apache.ldap.server.schema.OidRegistry#register(String, String)
177      */
178     public void register( String name, String oid )
179     {
180         if ( ! Character.isDigit( oid.charAt( 0 ) ) )
181         {
182             throw new RuntimeException( "Swap the parameter order: the oid " +
183                 "does not start with a digit!" );
184         }
185 
186         /*
187          * Add the entry for the given name as is and its lowercased version if
188          * the lower cased name is different from the given name name.  
189          */
190         String lowerCase = name.toLowerCase();
191         if ( ! lowerCase.equals( name ) )
192         {
193             byName.put( lowerCase, oid );
194         }
195         
196         // Put both the name and the oid as names
197         byName.put( name, oid );
198         byName.put( oid, oid );
199         
200         /*
201          * Update OID Map
202          * 
203          * 1). Check if we already have a value[s] stored
204          *      1a). Value is a single value and is a String
205          *          Replace value with list containing old and new values
206          *      1b). More than one value stored in a list
207          *          Add new value to the list
208          * 2). If we do not have a value then we just add it as a String
209          */
210         Object value = null;
211         if ( ! byOid.containsKey( oid ) )
212         {
213             value = name;
214         }
215         else 
216         {
217             ArrayList list = null;
218             value = byOid.get( oid );
219             
220             if ( value instanceof String )
221             {
222                 String existingName = ( String ) value;
223                 
224                 // if the existing name is already there we don't readd it
225                 if ( existingName.equalsIgnoreCase( name ) )
226                 {
227                     return;
228                 }
229                 
230                 list = new ArrayList();
231                 list.add( value );
232                 value = list;
233             }
234             else if ( value instanceof ArrayList )
235             {
236                 list = ( ArrayList ) value;
237                 
238                 for ( int ii = 0; ii < list.size(); ii++ )
239                 {
240                     // One form or another of the name already exists in list
241                     if ( ! name.equalsIgnoreCase( ( String ) list.get( ii ) ) )
242                     {
243                         return;
244                     }
245                 }
246                 
247                 list.add( name );
248             }
249         }
250 
251         byOid.put( oid, value );
252         monitor.registered( name, oid );
253     }
254     
255     
256     /***
257      * Gets the monitor.
258      * 
259      * @return the monitor
260      */
261     OidRegistryMonitor getMonitor()
262     {
263         return monitor;
264     }
265 
266     
267     /***
268      * Sets the monitor.
269      * 
270      * @param monitor monitor to set.
271      */
272     void setMonitor( OidRegistryMonitor monitor )
273     {
274         this.monitor = monitor;
275     }
276 }
277