001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.server.schema.registries;
021    
022    
023    import java.util.Iterator;
024    import java.util.Map;
025    import java.util.concurrent.ConcurrentHashMap;
026    
027    import javax.naming.NamingException;
028    
029    import org.apache.directory.shared.asn1.primitives.OID;
030    import org.apache.directory.shared.ldap.schema.ObjectClass;
031    import org.apache.directory.shared.ldap.util.StringTools;
032    import org.slf4j.Logger;
033    import org.slf4j.LoggerFactory;
034    
035    
036    /**
037     * A plain old java object implementation of an ObjectClassRegistry.
038     *
039     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040     * @version $Rev: 778529 $
041     */
042    public class DefaultObjectClassRegistry implements ObjectClassRegistry
043    {
044        /** static class logger */
045        private static final Logger LOG = LoggerFactory.getLogger( DefaultObjectClassRegistry.class );
046        
047        /** Speedup for DEBUG mode */
048        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
049        
050        /** maps an OID to an ObjectClass */
051        private final Map<String,ObjectClass> byOidOC;
052        
053        /** the registry used to resolve names to OIDs */
054        private final OidRegistry oidRegistry;
055    
056    
057        // ------------------------------------------------------------------------
058        // C O N S T R U C T O R S
059        // ------------------------------------------------------------------------
060    
061        /**
062         * Creates an empty DefaultObjectClassRegistry.
063         *
064         * @param oidRegistry used by this registry for OID to name resolution of
065         * dependencies and to automatically register and unregister it's aliases and OIDs
066         */
067        public DefaultObjectClassRegistry( OidRegistry oidRegistry )
068        {
069            byOidOC = new ConcurrentHashMap<String,ObjectClass>();
070            this.oidRegistry = oidRegistry;
071        }
072    
073        
074        // ------------------------------------------------------------------------
075        // Service Methods
076        // ------------------------------------------------------------------------
077        /**
078         * {@inheritDoc}
079         */
080        public void register( ObjectClass objectClass ) throws NamingException
081        {
082            String oid = objectClass.getOid();
083            
084            if ( byOidOC.containsKey( oid ) )
085            {
086                String msg = "objectClass " + objectClass.getName() + " w/ OID " + oid
087                    + " has already been registered!";
088                LOG.warn( msg );
089                throw new NamingException( msg );
090            }
091    
092            // Register the name/oid relation
093            String name = objectClass.getName();
094            
095            if ( !StringTools.isEmpty( name ) )
096            {
097                oidRegistry.register( name, oid );
098            }
099            
100            // Also register the oid/oid relation
101            oidRegistry.register( oid, oid );
102            
103            // Stores the OC in the internal map
104            byOidOC.put( oid, objectClass );
105            
106            if ( IS_DEBUG )
107            {
108                LOG.debug( "registered objectClass: {}", objectClass );
109            }
110        }
111    
112    
113        /**
114         * {@inheritDoc}
115         */
116        public ObjectClass lookup( String id ) throws NamingException
117        {
118            String ocId = StringTools.trim( id ).toLowerCase();
119            
120            if ( StringTools.isEmpty( ocId ) )
121            {
122                String msg = "Lookup in the OC registry : name should not be empty";
123                LOG.error( msg );
124                throw new NamingException( msg );
125            }
126            
127            String oid = oidRegistry.getOid( ocId );
128    
129            ObjectClass objectClass = byOidOC.get( oid );
130    
131            if ( objectClass == null )
132            {
133                String msg = "objectClass " + id + " w/ OID " + oid + " not registered!";
134                LOG.warn( msg );
135                throw new NamingException( msg );
136            }
137            
138            if ( IS_DEBUG )
139            {
140                LOG.debug( "looked objectClass with OID '{}' and got back {}", oid, objectClass );
141            }
142            
143            return objectClass;
144        }
145    
146    
147        /**
148         * {@inheritDoc}
149         */
150        public boolean hasObjectClass( String id )
151        {
152            try
153            {
154                String oid = oidRegistry.getOid( id );
155                
156                if ( oid == null )
157                {
158                    return false;
159                }
160                
161                return byOidOC.containsKey( oid );
162            }
163            catch ( NamingException e )
164            {
165                return false;
166            }
167        }
168    
169    
170        /**
171         * {@inheritDoc}
172         */
173        public String getSchemaName( String id ) throws NamingException
174        {
175            String ocOid = oidRegistry.getOid( id );
176            
177            if ( ocOid == null )
178            {
179                String msg = "Element " + id + " not found in the OID registry !";
180                LOG.warn( msg );
181                throw new NamingException( msg );
182            }
183    
184            ObjectClass oc = byOidOC.get( ocOid );
185            
186            if ( oc != null )
187            {
188                return oc.getSchema();
189            }
190    
191            String msg = "OID " + id + " not found in oid to " + "ObjectClass map!";
192            LOG.warn( msg );
193            throw new NamingException( msg );
194        }
195    
196    
197        /**
198         * {@inheritDoc}
199         */
200        public Iterator<ObjectClass> iterator()
201        {
202            return byOidOC.values().iterator();
203        }
204        
205        
206        /**
207         * {@inheritDoc}
208         */
209        public void unregister( String numericOid ) throws NamingException
210        {
211            if ( ! OID.isOID( numericOid ) )
212            {
213                String msg = "Looks like the arg " + numericOid + " is not a numeric OID";
214                LOG.warn( msg );
215                throw new NamingException( msg );
216            }
217    
218            byOidOC.remove( numericOid );
219        }
220    }