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.core.schema;
021    
022    
023    import java.util.Collection;
024    import java.util.Collections;
025    import java.util.HashSet;
026    import java.util.Set;
027    
028    import org.apache.directory.server.core.authn.AuthenticationInterceptor;
029    import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
030    import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
031    import org.apache.directory.server.core.exception.ExceptionInterceptor;
032    import org.apache.directory.server.core.interceptor.context.OperationContext;
033    import org.apache.directory.server.utils.AttributesFactory;
034    import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
035    import org.apache.directory.shared.ldap.constants.SchemaConstants;
036    import org.apache.directory.shared.ldap.entry.DefaultServerEntry;
037    import org.apache.directory.shared.ldap.entry.Entry;
038    import org.apache.directory.shared.ldap.entry.ServerEntry;
039    import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
040    import org.apache.directory.shared.ldap.name.DN;
041    import org.apache.directory.shared.ldap.schema.AttributeType;
042    import org.apache.directory.shared.ldap.schema.DITContentRule;
043    import org.apache.directory.shared.ldap.schema.DITStructureRule;
044    import org.apache.directory.shared.ldap.schema.LdapSyntax;
045    import org.apache.directory.shared.ldap.schema.MatchingRule;
046    import org.apache.directory.shared.ldap.schema.MatchingRuleUse;
047    import org.apache.directory.shared.ldap.schema.NameForm;
048    import org.apache.directory.shared.ldap.schema.ObjectClass;
049    import org.apache.directory.shared.ldap.schema.SchemaManager;
050    import org.apache.directory.shared.ldap.schema.SchemaObject;
051    import org.apache.directory.shared.ldap.schema.parsers.LdapComparatorDescription;
052    import org.apache.directory.shared.ldap.schema.parsers.NormalizerDescription;
053    import org.apache.directory.shared.ldap.schema.parsers.SyntaxCheckerDescription;
054    import org.apache.directory.shared.ldap.schema.registries.Schema;
055    import org.apache.directory.shared.ldap.util.Base64;
056    
057    
058    /**
059     * Responsible for translating modify operations on the subschemaSubentry into 
060     * operations against entries within the schema partition.
061     *
062     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
063     * @version $Rev$
064     */
065    public class SchemaSubentryModifier
066    {
067        private static final Collection<String> BYPASS;
068        
069        static
070        {
071            Set<String> c = new HashSet<String>();
072            c.add( AuthenticationInterceptor.class.getName() );
073            c.add( AciAuthorizationInterceptor.class.getName() );
074            c.add( DefaultAuthorizationInterceptor.class.getName() );
075            c.add( ExceptionInterceptor.class.getName() );
076            c.add( SchemaInterceptor.class.getName() );
077            BYPASS = Collections.unmodifiableCollection( c );
078        }
079        
080        private AttributesFactory factory = new AttributesFactory();
081        
082        /** The server schemaManager */
083        private SchemaManager schemaManager; 
084    
085        
086        /**
087         * 
088         * Creates a new instance of SchemaSubentryModifier.
089         *
090         * @param schemaManager The server schemaManager
091         * @param dao
092         */
093        public SchemaSubentryModifier( SchemaManager schemaManager )
094        {
095            this.schemaManager = schemaManager;
096        }
097        
098        
099        private DN getDn( SchemaObject obj ) throws LdapInvalidDnException
100        {
101            StringBuffer buf = new StringBuffer();
102            buf.append( "m-oid=" ).append( obj.getOid() ).append( ",ou=" );
103    
104            if ( obj instanceof LdapSyntax )
105            {
106                buf.append( "syntaxes" );
107            }
108            else if ( obj instanceof MatchingRule )
109            {
110                buf.append( SchemaConstants.MATCHING_RULES_AT );
111            }
112            else if ( obj instanceof AttributeType )
113            {
114                buf.append( SchemaConstants.ATTRIBUTE_TYPES_AT );
115            }
116            else if ( obj instanceof ObjectClass )
117            {
118                buf.append( SchemaConstants.OBJECT_CLASSES_AT );
119            }
120            else if ( obj instanceof MatchingRuleUse )
121            {
122                buf.append( SchemaConstants.MATCHING_RULE_USE_AT );
123            }
124            else if ( obj instanceof DITStructureRule )
125            {
126                buf.append( SchemaConstants.DIT_STRUCTURE_RULES_AT );
127            }
128            else if ( obj instanceof DITContentRule )
129            {
130                buf.append( SchemaConstants.DIT_CONTENT_RULES_AT );
131            }
132            else if ( obj instanceof NameForm )
133            {
134                buf.append( SchemaConstants.NAME_FORMS_AT );
135            }
136    
137            buf.append( ",cn=" ).append( obj.getSchemaName() ).append( ",ou=schema" );
138            return new DN( buf.toString() );
139        }
140        
141    
142        public void add( OperationContext opContext, LdapComparatorDescription comparatorDescription ) throws Exception
143        {
144            String schemaName = getSchema( comparatorDescription );   
145            DN dn = new DN( 
146                "m-oid=" + comparatorDescription.getOid(),
147                SchemaConstants.COMPARATORS_PATH,
148                "cn=" + schemaName,
149                SchemaConstants.OU_SCHEMA );
150            
151            Entry entry = getEntry( dn, comparatorDescription );
152    
153            opContext.add( (ServerEntry)entry, BYPASS );
154        }
155        
156        
157        public void add( OperationContext opContext, NormalizerDescription normalizerDescription ) throws Exception
158        {
159            String schemaName = getSchema( normalizerDescription );
160            DN dn = new DN( 
161                "m-oid=" + normalizerDescription.getOid(),
162                SchemaConstants.NORMALIZERS_PATH , 
163                "cn=" + schemaName,
164                SchemaConstants.OU_SCHEMA );
165            
166            Entry entry = getEntry( dn, normalizerDescription );
167    
168            opContext.add( (ServerEntry)entry, BYPASS );
169        }
170        
171        
172        public void add( OperationContext opContext, SyntaxCheckerDescription syntaxCheckerDescription ) throws Exception
173        {
174            String schemaName = getSchema( syntaxCheckerDescription );
175            DN dn = new DN( 
176                "m-oid=" + syntaxCheckerDescription.getOid(),
177                SchemaConstants.SYNTAX_CHECKERS_PATH,
178                "cn=" + schemaName, 
179                SchemaConstants.OU_SCHEMA );
180            
181            Entry entry = getEntry( dn, syntaxCheckerDescription );
182            opContext.add( (ServerEntry)entry, BYPASS );
183        }
184        
185        
186        public void addSchemaObject( OperationContext opContext, SchemaObject obj ) throws Exception
187        {
188            Schema schema = schemaManager.getLoadedSchema( obj.getSchemaName() );
189            DN dn = getDn( obj );
190            ServerEntry entry = factory.getAttributes( obj, schema, schemaManager );
191            entry.setDn( dn );
192    
193            opContext.add( entry, BYPASS );
194        }
195    
196    
197        public void deleteSchemaObject( OperationContext opContext, SchemaObject obj ) throws Exception
198        {
199            DN dn = getDn( obj );
200            opContext.delete( dn, BYPASS );
201        }
202    
203        
204        public void delete( OperationContext opContext, NormalizerDescription normalizerDescription ) throws Exception
205        {
206            String schemaName = getSchema( normalizerDescription );
207            DN dn = new DN( 
208                "m-oid=" + normalizerDescription.getOid(),
209                SchemaConstants.NORMALIZERS_PATH,
210                "cn=" + schemaName, 
211                SchemaConstants.OU_SCHEMA );
212            
213            opContext.delete( dn, BYPASS );
214        }
215    
216    
217        public void delete( OperationContext opContext, SyntaxCheckerDescription syntaxCheckerDescription ) throws Exception
218        {
219            String schemaName = getSchema( syntaxCheckerDescription );
220            DN dn = new DN( 
221                "m-oid=" + syntaxCheckerDescription.getOid(), 
222                SchemaConstants.SYNTAX_CHECKERS_PATH,
223                "cn=" + schemaName,
224                SchemaConstants.OU_SCHEMA );
225            opContext.delete( dn, BYPASS );
226        }
227    
228    
229        public void delete( OperationContext opContext, LdapComparatorDescription comparatorDescription ) throws Exception
230        {
231            String schemaName = getSchema( comparatorDescription );
232            DN dn = new DN( 
233                "m-oid=" + comparatorDescription.getOid(),
234                SchemaConstants.COMPARATORS_PATH,
235                "cn=" + schemaName,
236                SchemaConstants.OU_SCHEMA );
237            
238            opContext.delete( dn, BYPASS );
239        }
240    
241    
242        private Entry getEntry( DN dn, LdapComparatorDescription comparatorDescription )
243        {
244            Entry entry = new DefaultServerEntry( schemaManager, dn );
245            
246            entry.put( SchemaConstants.OBJECT_CLASS_AT, 
247                        SchemaConstants.TOP_OC, 
248                        MetaSchemaConstants.META_TOP_OC,
249                        MetaSchemaConstants.META_COMPARATOR_OC );
250            
251            entry.put( MetaSchemaConstants.M_OID_AT, comparatorDescription.getOid() );
252            entry.put( MetaSchemaConstants.M_FQCN_AT, comparatorDescription.getFqcn() );
253    
254            if ( comparatorDescription.getBytecode() != null )
255            {
256                entry.put( MetaSchemaConstants.M_BYTECODE_AT, 
257                    Base64.decode( comparatorDescription.getBytecode().toCharArray() ) );
258            }
259            
260            if ( comparatorDescription.getDescription() != null )
261            {
262                entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, comparatorDescription.getDescription() );
263            }
264            
265            return entry;
266        }
267    
268    
269        private Entry getEntry( DN dn, NormalizerDescription normalizerDescription )
270        {
271            Entry entry = new DefaultServerEntry( schemaManager, dn );
272    
273            entry.put( SchemaConstants.OBJECT_CLASS_AT, 
274                SchemaConstants.TOP_OC, 
275                MetaSchemaConstants.META_TOP_OC,
276                MetaSchemaConstants.META_NORMALIZER_OC );
277            
278            entry.put( MetaSchemaConstants.M_OID_AT, normalizerDescription.getOid() );
279            entry.put( MetaSchemaConstants.M_FQCN_AT, normalizerDescription.getFqcn() );
280    
281            if ( normalizerDescription.getBytecode() != null )
282            {
283                entry.put( MetaSchemaConstants.M_BYTECODE_AT, 
284                    Base64.decode( normalizerDescription.getBytecode().toCharArray() ) );
285            }
286            
287            if ( normalizerDescription.getDescription() != null )
288            {
289                entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, normalizerDescription.getDescription() );
290            }
291            
292            return entry;
293        }
294    
295    
296        private String getSchema( SchemaObject desc ) 
297        {
298            if ( desc.getExtensions().containsKey( MetaSchemaConstants.X_SCHEMA ) )
299            {
300                return desc.getExtensions().get( MetaSchemaConstants.X_SCHEMA ).get( 0 );
301            }
302            
303            return MetaSchemaConstants.SCHEMA_OTHER;
304        }
305        
306        
307        private Entry getEntry( DN dn, SyntaxCheckerDescription syntaxCheckerDescription )
308        {
309            Entry entry = new DefaultServerEntry( schemaManager, dn );
310            
311            entry.put( SchemaConstants.OBJECT_CLASS_AT, 
312                SchemaConstants.TOP_OC, 
313                MetaSchemaConstants.META_TOP_OC,
314                MetaSchemaConstants.META_SYNTAX_CHECKER_OC );
315    
316            entry.put( MetaSchemaConstants.M_OID_AT, syntaxCheckerDescription.getOid() );
317            entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxCheckerDescription.getFqcn() );
318    
319            if ( syntaxCheckerDescription.getBytecode() != null )
320            {
321                entry.put( MetaSchemaConstants.M_BYTECODE_AT, 
322                    Base64.decode( syntaxCheckerDescription.getBytecode().toCharArray() ) );
323            }
324            
325            if ( syntaxCheckerDescription.getDescription() != null )
326            {
327                entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, syntaxCheckerDescription.getDescription() );
328            }
329            
330            return entry;
331        }
332    }