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.ArrayList;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.concurrent.ConcurrentHashMap;
028    
029    import javax.naming.NamingException;
030    
031    import org.apache.directory.shared.asn1.primitives.OID;
032    import org.apache.directory.shared.ldap.schema.SyntaxChecker;
033    import org.apache.directory.shared.ldap.schema.parsers.SyntaxCheckerDescription;
034    import org.slf4j.Logger;
035    import org.slf4j.LoggerFactory;
036    
037    
038    /**
039     * The POJO implementation for the SyntaxCheckerRegistry service.
040     *
041     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042     * @version $Rev: 778529 $
043     */
044    public class DefaultSyntaxCheckerRegistry implements SyntaxCheckerRegistry
045    {
046        /** static class logger */
047        private static final Logger LOG = LoggerFactory.getLogger( DefaultSyntaxCheckerRegistry.class );
048        
049        /** a map by OID of SyntaxCheckers */
050        private final Map<String, SyntaxChecker> byOidSyntaxChecker;
051        
052        /** maps an OID to a syntaxCheckerDescription */
053        private final Map<String, SyntaxCheckerDescription> oidToDescription;
054    
055    
056        // ------------------------------------------------------------------------
057        // C O N S T R U C T O R S
058        // ------------------------------------------------------------------------
059        /**
060         * Creates an instance of a DefaultSyntaxRegistry.
061         */
062        public DefaultSyntaxCheckerRegistry()
063        {
064            byOidSyntaxChecker = new ConcurrentHashMap<String, SyntaxChecker>();
065            oidToDescription = new ConcurrentHashMap<String, SyntaxCheckerDescription>();
066        }
067    
068    
069        // ------------------------------------------------------------------------
070        // Service Methods
071        // ------------------------------------------------------------------------
072        /**
073         * {@inheritDoc}
074         */
075        public void register( SyntaxCheckerDescription syntaxCheckerDescription, SyntaxChecker syntaxChecker ) throws NamingException
076        {
077            String oid = syntaxChecker.getSyntaxOid();
078            
079            if ( byOidSyntaxChecker.containsKey( oid ) )
080            {
081                String msg = "SyntaxChecker with OID " + oid + " already registered!";
082                LOG.warn( msg );
083                throw new NamingException( msg );
084            }
085    
086            byOidSyntaxChecker.put( oid, syntaxChecker );
087            oidToDescription.put( oid, syntaxCheckerDescription );
088            
089            if ( LOG.isDebugEnabled() )
090            {
091                LOG.debug( "registered syntaxChecher for OID {}", oid );
092            }
093        }
094    
095    
096        /**
097         * {@inheritDoc}
098         */
099        public SyntaxChecker lookup( String oid ) throws NamingException
100        {
101            SyntaxChecker syntaxChecker = byOidSyntaxChecker.get( oid );
102    
103            if ( syntaxChecker == null )
104            {
105                String msg = "SyntaxChecker for OID " + oid + " not found!";
106                LOG.warn( msg );
107                throw new NamingException( msg );
108            }
109            
110            if ( LOG.isDebugEnabled() )
111            {
112                LOG.debug( "looked up syntaxChecher with OID {}", oid );
113            }
114    
115            return syntaxChecker;
116        }
117    
118    
119        /**
120         * {@inheritDoc}
121         */
122        public boolean hasSyntaxChecker( String oid )
123        {
124            return byOidSyntaxChecker.containsKey( oid );
125        }
126    
127    
128        /**
129         * {@inheritDoc}
130         */
131        public String getSchemaName( String oid ) throws NamingException
132        {
133            if ( ! OID.isOID( oid ) )
134            {
135                String msg = "Looks like the arg is not a numeric OID";
136                LOG.warn( msg );
137                throw new NamingException( msg );
138            }
139    
140            SyntaxCheckerDescription description = oidToDescription.get( oid );
141            
142            if ( description != null )
143            {
144                return getSchema( description );
145            }
146    
147            String msg = "OID " + oid + " not found in oid to schema name map!";
148            LOG.warn( msg );
149            throw new NamingException( msg );
150        }
151        
152        
153        private static String getSchema( SyntaxCheckerDescription desc ) 
154        {
155            List<String> ext = desc.getExtensions().get( "X-SCHEMA" );
156            
157            if ( ( ext == null ) || ( ext.size() == 0 ) )
158            {
159                return "other";
160            }
161            
162            return ext.get( 0 );
163        }
164    
165    
166        /**
167         * {@inheritDoc}
168         */
169        public Iterator<SyntaxChecker> iterator()
170        {
171            return byOidSyntaxChecker.values().iterator();
172        }
173    
174    
175        /**
176         * {@inheritDoc}
177         */
178        public void unregister( String numericOid ) throws NamingException
179        {
180            if ( ! OID.isOID( numericOid ) )
181            {
182                String msg = "Looks like the arg is not a numeric OID";
183                LOG.warn( msg );
184                throw new NamingException( msg );
185            }
186    
187            byOidSyntaxChecker.remove( numericOid );
188            oidToDescription.remove( numericOid );
189        }
190        
191        
192        /**
193         * {@inheritDoc}
194         */
195        public void unregisterSchemaElements( String schemaName )
196        {
197            List<String> oids = new ArrayList<String>( byOidSyntaxChecker.keySet() );
198            
199            for ( String oid : oids )
200            {
201                SyntaxCheckerDescription description = oidToDescription.get( oid );
202                String schemaNameForOid = getSchema( description );
203                
204                if ( schemaNameForOid.equalsIgnoreCase( schemaName ) )
205                {
206                    byOidSyntaxChecker.remove( oid );
207                    oidToDescription.remove( oid );
208                }
209            }
210        }
211    
212    
213        /**
214         * {@inheritDoc}
215         */
216        public void renameSchema( String originalSchemaName, String newSchemaName )
217        {
218            List<String> oids = new ArrayList<String>( byOidSyntaxChecker.keySet() );
219            
220            for ( String oid : oids )
221            {
222                SyntaxCheckerDescription description = oidToDescription.get( oid );
223                String schemaNameForOid = getSchema( description );
224                
225                if ( schemaNameForOid.equalsIgnoreCase( originalSchemaName ) )
226                {
227                    List<String> values = description.getExtensions().get( "X-SCHEMA" );
228                    values.clear();
229                    values.add( newSchemaName );
230                }
231            }
232        }
233    
234    
235        /**
236         * {@inheritDoc}
237         */
238        public Iterator<SyntaxCheckerDescription> syntaxCheckerDescriptionIterator()
239        {
240            return oidToDescription.values().iterator();
241        }
242    }