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.ArrayList;
024    import java.util.HashMap;
025    import java.util.HashSet;
026    import java.util.List;
027    import java.util.Map;
028    import java.util.Set;
029    
030    import javax.naming.NamingException;
031    import javax.naming.directory.SearchControls;
032    
033    import org.apache.directory.server.constants.ServerDNConstants;
034    import org.apache.directory.server.core.filtering.EntryFilteringCursor;
035    import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
036    import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
037    import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
038    import org.apache.directory.server.core.partition.Partition;
039    import org.apache.directory.server.i18n.I18n;
040    import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
041    import org.apache.directory.shared.ldap.constants.SchemaConstants;
042    import org.apache.directory.shared.ldap.entry.StringValue;
043    import org.apache.directory.shared.ldap.entry.DefaultServerAttribute;
044    import org.apache.directory.shared.ldap.entry.EntryAttribute;
045    import org.apache.directory.shared.ldap.entry.Modification;
046    import org.apache.directory.shared.ldap.entry.ModificationOperation;
047    import org.apache.directory.shared.ldap.entry.ServerEntry;
048    import org.apache.directory.shared.ldap.entry.ServerModification;
049    import org.apache.directory.shared.ldap.filter.AndNode;
050    import org.apache.directory.shared.ldap.filter.BranchNode;
051    import org.apache.directory.shared.ldap.filter.EqualityNode;
052    import org.apache.directory.shared.ldap.filter.ExprNode;
053    import org.apache.directory.shared.ldap.filter.OrNode;
054    import org.apache.directory.shared.ldap.filter.PresenceNode;
055    import org.apache.directory.shared.ldap.filter.SearchScope;
056    import org.apache.directory.shared.ldap.filter.SimpleNode;
057    import org.apache.directory.shared.ldap.message.AliasDerefMode;
058    import org.apache.directory.shared.ldap.name.DN;
059    import org.apache.directory.shared.ldap.name.RDN;
060    import org.apache.directory.shared.ldap.schema.AttributeType;
061    import org.apache.directory.shared.ldap.schema.AttributeTypeOptions;
062    import org.apache.directory.shared.ldap.schema.MatchingRule;
063    import org.apache.directory.shared.ldap.schema.ObjectClass;
064    import org.apache.directory.shared.ldap.schema.SchemaManager;
065    import org.apache.directory.shared.ldap.schema.loader.ldif.SchemaEntityFactory;
066    import org.apache.directory.shared.ldap.schema.registries.Schema;
067    import org.apache.directory.shared.ldap.schema.syntaxCheckers.NumericOidSyntaxChecker;
068    import org.apache.directory.shared.ldap.util.DateUtils;
069    import org.slf4j.Logger;
070    import org.slf4j.LoggerFactory;
071    
072    
073    /**
074     * A specialized data access object for managing schema objects in the
075     * schema partition.  
076     * 
077     * WARNING:
078     * This dao operates directly on a partition.  Hence no interceptors are available
079     * to perform the various expected services of respective interceptors.  Take care
080     * to normalize all filters and distinguished names.
081     * 
082     * A single write operation exists for enabling schemas needed for operating indices
083     * in partitions and enabling schemas that are dependencies of other schemas that 
084     * are enabled.  In both these limited cases there is no need to worry about issues
085     * with a lack of replication propagation because these same updates will take place
086     * on replicas when the original operation is propagated or when replicas start up.
087     * 
088     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
089     * @version $Rev$
090     */
091    public class SchemaPartitionDaoImpl implements SchemaPartitionDao
092    {
093        /** static class logger */
094        private final Logger LOG = LoggerFactory.getLogger( getClass() );
095        private static final NumericOidSyntaxChecker NUMERIC_OID_CHECKER = new NumericOidSyntaxChecker();
096        private static final String[] SCHEMA_ATTRIBUTES = new String[]
097            { SchemaConstants.CREATORS_NAME_AT_OID, "m-dependencies", SchemaConstants.OBJECT_CLASS_AT_OID, 
098              SchemaConstants.CN_AT_OID, "m-disabled" };
099    
100        private final Partition partition;
101        private final SchemaEntityFactory factory;
102        private final SchemaManager schemaManager;
103    
104        private final String M_NAME_OID;
105        private final String CN_OID;
106        private final String M_OID_OID;
107        private final String OBJECTCLASS_OID;
108        private final String M_SYNTAX_OID;
109        private final String M_ORDERING_OID;
110        private final String M_SUBSTRING_OID;
111        private final String M_EQUALITY_OID;
112        private final String M_SUP_ATTRIBUTE_TYPE_OID;
113        private final String M_MUST_OID;
114        private final String M_MAY_OID;
115        private final String M_AUX_OID;
116        private final String M_OC_OID;
117        private final String M_SUP_OBJECT_CLASS_OID;
118        private final String M_DEPENDENCIES_OID;
119    
120        private final Set<AttributeTypeOptions> schemaAttributesToReturn = new HashSet<AttributeTypeOptions>();
121        private final AttributeType disabledAttributeType;
122    
123    
124        /**
125         * Creates a schema dao object backing information within a schema partition.
126         * 
127         * @param partition the schema partition
128         * @param registries the bootstrap registries that were used to start up the schema partition
129         * @throws NamingException if there are problems initializing this schema partion dao
130         */
131        public SchemaPartitionDaoImpl( Partition partition, SchemaManager schemaManager ) throws Exception
132        {
133            this.partition = partition;
134            this.factory = new SchemaEntityFactory();
135            this.schemaManager = schemaManager;
136    
137            this.M_NAME_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_NAME_AT );
138            this.CN_OID = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.CN_AT );
139            this.disabledAttributeType = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_DISABLED_AT );
140            this.M_OID_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_OID_AT );
141            this.OBJECTCLASS_OID = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.OBJECT_CLASS_AT );
142            this.M_SYNTAX_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_SYNTAX_AT );
143            this.M_ORDERING_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_ORDERING_AT );
144            this.M_EQUALITY_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_EQUALITY_AT );
145            this.M_SUBSTRING_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_SUBSTR_AT );
146            this.M_SUP_ATTRIBUTE_TYPE_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_SUP_ATTRIBUTE_TYPE_AT );
147            this.M_MUST_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_MUST_AT );
148            this.M_MAY_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_MAY_AT );
149            this.M_AUX_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_AUX_AT );
150            this.M_OC_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_OC_AT );
151            this.M_SUP_OBJECT_CLASS_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_SUP_OBJECT_CLASS_AT );
152            this.M_DEPENDENCIES_OID = schemaManager.getAttributeTypeRegistry().getOidByName( MetaSchemaConstants.M_DEPENDENCIES_AT );
153            
154            for ( String attrId : SCHEMA_ATTRIBUTES )
155            {
156                AttributeTypeOptions ato = new AttributeTypeOptions( schemaManager.lookupAttributeTypeRegistry( attrId ) );
157                schemaAttributesToReturn.add( ato );
158            }
159        }
160    
161    
162        /* (non-Javadoc)
163         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#getSchemas()
164         */
165        public Map<String, Schema> getSchemas() throws Exception
166        {
167            Map<String, Schema> schemas = new HashMap<String, Schema>();
168            EntryFilteringCursor list = listSchemas();
169    
170            while ( list.next() )
171            {
172                ServerEntry sr = list.get();
173                Schema schema = factory.getSchema( sr );
174                schemas.put( schema.getSchemaName(), schema );
175            }
176    
177            return schemas;
178        }
179    
180    
181        /* (non-Javadoc)
182         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#getSchemaNames()
183         */
184        public Set<String> getSchemaNames() throws Exception
185        {
186            Set<String> schemaNames = new HashSet<String>();
187            EntryFilteringCursor list = listSchemas();
188    
189            while ( list.next() )
190            {
191                ServerEntry sr = list.get();
192                schemaNames.add( sr.get( SchemaConstants.CN_AT ).getString() );
193            }
194    
195            return schemaNames;
196        }
197    
198    
199        private EntryFilteringCursor listSchemas() throws Exception
200        {
201            DN base = new DN( SchemaConstants.OU_SCHEMA );
202            base.normalize( schemaManager.getNormalizerMapping() );
203            ExprNode filter = new EqualityNode<String>( schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.OBJECT_CLASS_AT ),
204                new StringValue( MetaSchemaConstants.META_SCHEMA_OC ) );
205    
206            SearchOperationContext searchContext = new SearchOperationContext( null );
207            searchContext.setDn( base );
208            searchContext.setScope( SearchScope.ONELEVEL );
209            searchContext.setReturningAttributes( schemaAttributesToReturn );
210            searchContext.setFilter( filter );
211            return partition.search( searchContext );
212        }
213    
214    
215        /* (non-Javadoc)
216         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#getSchema(java.lang.String)
217         */
218        public Schema getSchema( String schemaName ) throws Exception
219        {
220            DN dn = new DN( "cn=" + schemaName + ",ou=schema" );
221            dn.normalize( schemaManager.getNormalizerMapping() );
222            return factory.getSchema( partition.lookup( new LookupOperationContext( null, dn ) ) );
223        }
224    
225    
226        /* (non-Javadoc)
227         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#hasMatchingRule(java.lang.String)
228         */
229        public boolean hasMatchingRule( String oid ) throws Exception
230        {
231            BranchNode filter = new AndNode();
232            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue(
233                MetaSchemaConstants.META_MATCHING_RULE_OC ) ) );
234    
235            if ( NUMERIC_OID_CHECKER.isValidSyntax( oid ) )
236            {
237                filter.addNode( new EqualityNode<String>( M_OID_OID, new StringValue( oid ) ) );
238            }
239            else
240            {
241                filter.addNode( new EqualityNode<String>( M_NAME_OID, new StringValue( oid.toLowerCase() ) ) );
242            }
243    
244            SearchControls searchControls = new SearchControls();
245            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
246            EntryFilteringCursor cursor = null;
247    
248            try
249            {
250                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
251                    filter, searchControls );
252                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
253                
254                cursor = partition.search( searchOperationContext );
255    
256                if ( !cursor.next() )
257                {
258                    return false;
259                }
260    
261                if ( cursor.next() )
262                {
263                    throw new NamingException( I18n.err( I18n.ERR_430, oid ) );
264                }
265    
266                return true;
267            }
268            finally
269            {
270                if ( cursor != null )
271                {
272                    cursor.close();
273                }
274            }
275        }
276    
277    
278        /* (non-Javadoc)
279         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#hasAttributeType(java.lang.String)
280         */
281        public boolean hasAttributeType( String oid ) throws Exception
282        {
283            BranchNode filter = new AndNode();
284            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue(
285                MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC ) ) );
286    
287            if ( NUMERIC_OID_CHECKER.isValidSyntax( oid ) )
288            {
289                filter.addNode( new EqualityNode<String>( M_OID_OID, new StringValue( oid ) ) );
290            }
291            else
292            {
293                filter.addNode( new EqualityNode<String>( M_NAME_OID, new StringValue( oid.toLowerCase() ) ) );
294            }
295    
296            SearchControls searchControls = new SearchControls();
297            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
298            EntryFilteringCursor cursor = null;
299    
300            try
301            {
302                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
303                    filter, searchControls );
304                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
305                
306                cursor = partition.search( searchOperationContext );
307    
308                if ( !cursor.next() )
309                {
310                    return false;
311                }
312    
313                if ( cursor.next() )
314                {
315                    throw new NamingException( I18n.err( I18n.ERR_431, oid ) );
316                }
317    
318                return true;
319            }
320            finally
321            {
322                if ( cursor != null )
323                {
324                    cursor.close();
325                }
326            }
327        }
328    
329    
330        /* (non-Javadoc)
331         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#hasObjectClass(java.lang.String)
332         */
333        public boolean hasObjectClass( String oid ) throws Exception
334        {
335            BranchNode filter = new AndNode();
336            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
337                new StringValue( MetaSchemaConstants.META_OBJECT_CLASS_OC ) ) );
338    
339            if ( NUMERIC_OID_CHECKER.isValidSyntax( oid ) )
340            {
341                filter.addNode( new EqualityNode<String>( M_OID_OID, new StringValue( oid ) ) );
342            }
343            else
344            {
345                filter.addNode( new EqualityNode<String>( M_NAME_OID, new StringValue( oid.toLowerCase() ) ) );
346            }
347    
348            SearchControls searchControls = new SearchControls();
349            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
350            EntryFilteringCursor cursor = null;
351    
352            try
353            {
354                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
355                    filter, searchControls );
356                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
357                
358                cursor = partition.search( searchOperationContext );
359    
360                if ( !cursor.next() )
361                {
362                    return false;
363                }
364    
365                if ( cursor.next() )
366                {
367                    throw new NamingException( I18n.err( I18n.ERR_431, oid ) );
368                }
369    
370                return true;
371            }
372            finally
373            {
374                if ( cursor != null )
375                {
376                    cursor.close();
377                }
378            }
379        }
380    
381    
382        /* (non-Javadoc)
383         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#hasSyntax(java.lang.String)
384         */
385        public boolean hasSyntax( String oid ) throws Exception
386        {
387            BranchNode filter = new AndNode();
388            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
389                    new StringValue( MetaSchemaConstants.META_SYNTAX_OC ) ) );
390    
391            if ( NUMERIC_OID_CHECKER.isValidSyntax( oid ) )
392            {
393                filter.addNode( new EqualityNode<String>( M_OID_OID, new StringValue( oid ) ) );
394            }
395            else
396            {
397                filter.addNode( new EqualityNode<String>( M_NAME_OID, new StringValue( oid.toLowerCase() ) ) );
398            }
399    
400            SearchControls searchControls = new SearchControls();
401            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
402            EntryFilteringCursor cursor = null;
403    
404            try
405            {
406                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
407                    filter, searchControls );
408                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
409                
410                cursor = partition.search( searchOperationContext );
411    
412                if ( !cursor.next() )
413                {
414                    return false;
415                }
416    
417                if ( cursor.next() )
418                {
419                    throw new NamingException( I18n.err( I18n.ERR_432, oid ) );
420                }
421    
422                return true;
423            }
424            finally
425            {
426                if ( cursor != null )
427                {
428                    cursor.close();
429                }
430            }
431        }
432    
433    
434        /* (non-Javadoc)
435         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#hasSyntaxChecker(java.lang.String)
436         */
437        public boolean hasSyntaxChecker( String oid ) throws Exception
438        {
439            BranchNode filter = new AndNode();
440            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
441                new StringValue( MetaSchemaConstants.META_SYNTAX_CHECKER_OC ) ) );
442    
443            if ( NUMERIC_OID_CHECKER.isValidSyntax( oid ) )
444            {
445                filter.addNode( new EqualityNode<String>( M_OID_OID, new StringValue( oid ) ) );
446            }
447            else
448            {
449                filter.addNode( new EqualityNode<String>( M_NAME_OID, new StringValue( oid.toLowerCase() ) ) );
450            }
451    
452            SearchControls searchControls = new SearchControls();
453            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
454            EntryFilteringCursor cursor = null;
455    
456            try
457            {
458                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
459                    filter, searchControls );
460                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
461                
462                cursor = partition.search( searchOperationContext );
463    
464                if ( !cursor.next() )
465                {
466                    return false;
467                }
468    
469                if ( cursor.next() )
470                {
471                    throw new NamingException( I18n.err( I18n.ERR_433, oid ) );
472                }
473    
474                return true;
475            }
476            finally
477            {
478                if ( cursor != null )
479                {
480                    cursor.close();
481                }
482            }
483        }
484    
485    
486        /* (non-Javadoc)
487         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#findSchema(java.lang.String)
488         */
489        public String findSchema( String entityName ) throws Exception
490        {
491            DN dn = findDn( entityName );
492            if ( dn == null )
493            {
494                return null;
495            }
496    
497            RDN rdn = dn.getRdn( 1 );
498            
499            if ( !rdn.getNormType().equalsIgnoreCase( CN_OID ) )
500            {
501                throw new NamingException( I18n.err( I18n.ERR_434, dn.getNormName(), CN_OID, rdn.getNormType() ) );
502            }
503    
504            return ( String ) rdn.getNormValue();
505        }
506    
507    
508        /* (non-Javadoc)
509         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#findDn(java.lang.String)
510         */
511        public DN findDn( String entityName ) throws Exception
512        {
513            ServerEntry sr = find( entityName );
514            DN dn = sr.getDn();
515            dn.normalize( schemaManager.getNormalizerMapping() );
516            return dn;
517        }
518    
519    
520        /* (non-Javadoc)
521         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#find(java.lang.String)
522         */
523        public ServerEntry find( String entityName ) throws Exception
524        {
525            BranchNode filter = new OrNode();
526            SimpleNode<String> nameAVA = new EqualityNode<String>( M_NAME_OID, 
527                new StringValue( entityName.toLowerCase() ) );
528            SimpleNode<String> oidAVA = new EqualityNode<String>( M_OID_OID, 
529                new StringValue( entityName.toLowerCase() ) );
530            filter.addNode( nameAVA );
531            filter.addNode( oidAVA );
532            SearchControls searchControls = new SearchControls();
533            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
534            EntryFilteringCursor cursor = null;
535    
536            try
537            {
538                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
539                    filter, searchControls );
540                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
541                
542                cursor = partition.search( searchOperationContext );
543    
544                if ( !cursor.next() )
545                {
546                    return null;
547                }
548    
549                ServerEntry sr = cursor.get();
550                
551                if ( cursor.next() )
552                {
553                    throw new NamingException( I18n.err( I18n.ERR_435, entityName ) );
554                }
555    
556                return sr;
557            }
558            finally
559            {
560                if ( cursor != null )
561                {
562                    cursor.close();
563                }
564            }
565        }
566    
567    
568        /* (non-Javadoc)
569         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#enableSchema(java.lang.String)
570         */
571        public void enableSchema( String schemaName ) throws Exception
572        {
573            DN dn = new DN( "cn=" + schemaName + ",ou=schema" );
574            dn.normalize( schemaManager.getNormalizerMapping() );
575            ServerEntry entry = partition.lookup( new LookupOperationContext( null, dn ) );
576            EntryAttribute disabledAttr = entry.get( disabledAttributeType );
577            List<Modification> mods = new ArrayList<Modification>( 3 );
578    
579            if ( disabledAttr == null )
580            {
581                LOG.warn( "Does not make sense: you're trying to enable {} schema which is already enabled", schemaName );
582                return;
583            }
584    
585            boolean isDisabled = disabledAttr.contains( "TRUE" );
586            
587            if ( !isDisabled )
588            {
589                LOG.warn( "Does not make sense: you're trying to enable {} schema which is already enabled", schemaName );
590                return;
591            }
592    
593            mods.add( new ServerModification( ModificationOperation.REMOVE_ATTRIBUTE, new DefaultServerAttribute(
594                MetaSchemaConstants.M_DISABLED_AT, schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_DISABLED_AT ) ) ) );
595    
596            mods.add( new ServerModification( ModificationOperation.ADD_ATTRIBUTE, new DefaultServerAttribute(
597                SchemaConstants.MODIFIERS_NAME_AT, schemaManager.lookupAttributeTypeRegistry( SchemaConstants.MODIFIERS_NAME_AT ),
598                ServerDNConstants.ADMIN_SYSTEM_DN ) ) );
599    
600            mods.add( new ServerModification( ModificationOperation.ADD_ATTRIBUTE, new DefaultServerAttribute(
601                SchemaConstants.MODIFY_TIMESTAMP_AT, schemaManager.lookupAttributeTypeRegistry( SchemaConstants.MODIFY_TIMESTAMP_AT ), DateUtils
602                    .getGeneralizedTime() ) ) );
603    
604            partition.modify( new ModifyOperationContext( null, dn, mods ) );
605        }
606    
607    
608        /* (non-Javadoc)
609         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listSyntaxDependents(java.lang.String)
610         */
611        public Set<ServerEntry> listSyntaxDependents( String numericOid ) throws Exception
612        {
613            Set<ServerEntry> set = new HashSet<ServerEntry>();
614            BranchNode filter = new AndNode();
615    
616            // subfilter for (| (objectClass=metaMatchingRule) (objectClass=metaAttributeType))  
617            BranchNode or = new OrNode();
618            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
619                new StringValue( MetaSchemaConstants.META_MATCHING_RULE_OC.toLowerCase() ) ) );
620            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
621                new StringValue( MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC.toLowerCase() ) ) );
622    
623            filter.addNode( or );
624            filter.addNode( new EqualityNode<String>( M_SYNTAX_OID, new StringValue( numericOid.toLowerCase() ) ) );
625    
626            SearchControls searchControls = new SearchControls();
627            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
628            EntryFilteringCursor cursor = null;
629    
630            try
631            {
632                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
633                    filter, searchControls );
634                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
635                
636                cursor = partition.search( searchOperationContext );
637                
638                while ( cursor.next() )
639                {
640                    set.add( cursor.get() );
641                }
642            }
643            finally
644            {
645                if ( cursor != null )
646                {
647                    cursor.close();
648                }
649            }
650    
651            return set;
652        }
653    
654    
655        /* (non-Javadoc)
656         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listMatchingRuleDependents(org.apache.directory.shared.ldap.schema.MatchingRule)
657         */
658        public Set<ServerEntry> listMatchingRuleDependents( MatchingRule mr ) throws Exception
659        {
660            Set<ServerEntry> set = new HashSet<ServerEntry>();
661            BranchNode filter = new AndNode();
662    
663            // ( objectClass = metaAttributeType )
664            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue(
665                MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC.toLowerCase() ) ) );
666    
667            BranchNode or = new OrNode();
668            or.addNode( new EqualityNode<String>( M_ORDERING_OID, new StringValue( mr.getOid() ) ) );
669            or.addNode( new EqualityNode<String>( M_SUBSTRING_OID, new StringValue( mr.getOid() ) ) );
670            or.addNode( new EqualityNode<String>( M_EQUALITY_OID, new StringValue( mr.getOid() ) ) );
671            filter.addNode( or );
672    
673            List<String> names = mr.getNames();
674            
675            if ( ( names != null ) && ( names.size() > 0 ) )
676            {
677                for ( String name : names )
678                {
679                    or.addNode( new EqualityNode<String>( M_ORDERING_OID, new StringValue( name.toLowerCase() ) ) );
680                    or.addNode( new EqualityNode<String>( M_SUBSTRING_OID, new StringValue( name.toLowerCase() ) ) );
681                    or.addNode( new EqualityNode<String>( M_EQUALITY_OID, new StringValue( name.toLowerCase() ) ) );
682                }
683            }
684    
685            SearchControls searchControls = new SearchControls();
686            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
687            EntryFilteringCursor cursor = null;
688    
689            try
690            {
691                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
692                    filter, searchControls );
693                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
694                
695                cursor = partition.search( searchOperationContext );
696                
697                while ( cursor.next() )
698                {
699                    set.add( cursor.get() );
700                }
701            }
702            finally
703            {
704                if ( cursor != null )
705                {
706                    cursor.close();
707                }
708            }
709    
710            return set;
711        }
712    
713    
714        /* (non-Javadoc)
715         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listAllNames()
716         */
717        public EntryFilteringCursor listAllNames() throws Exception
718        {
719            SearchControls searchControls = new SearchControls();
720            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
721            BranchNode filter = new AndNode();
722    
723            // (& (m-oid=*) (m-name=*) )
724            filter.addNode( new PresenceNode( M_OID_OID ) );
725            filter.addNode( new PresenceNode( M_NAME_OID ) );
726    
727            SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
728                filter, searchControls );
729            searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
730            
731            return partition.search( searchOperationContext );
732        }
733    
734    
735        /* (non-Javadoc)
736         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listAttributeTypeDependents(org.apache.directory.shared.ldap.schema.AttributeType)
737         */
738        public Set<ServerEntry> listAttributeTypeDependents( AttributeType at ) throws Exception
739        {
740            /*
741             * Right now the following inefficient filter is being used:
742             * 
743             * ( & 
744             *      ( | ( objectClass = metaAttributeType ) ( objectClass = metaObjectClass ) )
745             *      ( | ( m-oid = $oid ) ( m-must = $oid ) ( m-supAttributeType = $oid ) )
746             * )
747             * 
748             * the reason why this is inefficient is because the or terms have large scan counts
749             * and several loops are going to be required.  The following search is better because
750             * it constrains the results better:
751             * 
752             * ( |
753             *      ( & ( objectClass = metaAttributeType ) ( m-supAttributeType = $oid ) )
754             *      ( & ( objectClass = metaObjectClass ) ( | ( m-may = $oid ) ( m-must = $oid ) ) )
755             * )
756             */
757    
758            Set<ServerEntry> set = new HashSet<ServerEntry>();
759            BranchNode filter = new AndNode();
760    
761            // ( objectClass = metaAttributeType )
762            BranchNode or = new OrNode();
763            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
764                new StringValue( MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC.toLowerCase() ) ) );
765            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
766                new StringValue( MetaSchemaConstants.META_OBJECT_CLASS_OC.toLowerCase() ) ) );
767            filter.addNode( or );
768    
769            or = new OrNode();
770            or.addNode( new EqualityNode<String>( M_MAY_OID, new StringValue( at.getOid() ) ) );
771            or.addNode( new EqualityNode<String>( M_MUST_OID, new StringValue( at.getOid() ) ) );
772            or.addNode( new EqualityNode<String>( M_SUP_ATTRIBUTE_TYPE_OID, new StringValue( at.getOid() ) ) );
773            filter.addNode( or );
774    
775            SearchControls searchControls = new SearchControls();
776            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
777            EntryFilteringCursor cursor = null;
778    
779            try
780            {
781                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
782                    filter, searchControls );
783                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
784                
785                cursor = partition.search( searchOperationContext );
786                
787                while ( cursor.next() )
788                {
789                    set.add( cursor.get() );
790                }
791            }
792            finally
793            {
794                if ( cursor != null )
795                {
796                    cursor.close();
797                }
798            }
799    
800            return set;
801        }
802    
803    
804        /* (non-Javadoc)
805         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listSchemaDependents(java.lang.String)
806         */
807        public Set<ServerEntry> listSchemaDependents( String schemaName ) throws Exception
808        {
809            /*
810             * The following filter is being used:
811             * 
812             * ( & ( objectClass = metaSchema ) ( m-dependencies = $schemaName ) )
813             */
814    
815            Set<ServerEntry> set = new HashSet<ServerEntry>();
816            BranchNode filter = new AndNode();
817    
818            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, 
819                new StringValue( MetaSchemaConstants.META_SCHEMA_OC.toLowerCase() ) ) );
820            filter.addNode( new EqualityNode<String>( M_DEPENDENCIES_OID, 
821                new StringValue( schemaName.toLowerCase() ) ) );
822    
823            SearchControls searchControls = new SearchControls();
824            searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
825            EntryFilteringCursor cursor = null;
826    
827            try
828            {
829                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
830                    filter, searchControls );
831                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
832                
833                cursor = partition.search( searchOperationContext );
834                
835                while ( cursor.next() )
836                {
837                    set.add( cursor.get() );
838                }
839            }
840            finally
841            {
842                if ( cursor != null )
843                {
844                    cursor.close();
845                }
846            }
847    
848            return set;
849        }
850    
851    
852        /* (non-Javadoc)
853         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listEnabledSchemaDependents(java.lang.String)
854         */
855        public Set<ServerEntry> listEnabledSchemaDependents( String schemaName ) throws Exception
856        {
857            Set<ServerEntry> set = new HashSet<ServerEntry>();
858            BranchNode filter = new AndNode();
859    
860            filter.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue( 
861                MetaSchemaConstants.META_SCHEMA_OC.toLowerCase() ) ) );
862            filter.addNode( new EqualityNode<String>( M_DEPENDENCIES_OID, new StringValue( 
863                schemaName.toLowerCase() ) ) );
864    
865            SearchControls searchControls = new SearchControls();
866            searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
867            EntryFilteringCursor cursor = null;
868    
869            try
870            {
871                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
872                    filter, searchControls );
873                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
874                
875                cursor = partition.search( searchOperationContext );
876    
877                while ( cursor.next() )
878                {
879                    ServerEntry sr = cursor.get();
880                    EntryAttribute disabled = sr.get( disabledAttributeType );
881    
882                    if ( disabled == null )
883                    {
884                        set.add( sr );
885                    }
886                    else if ( disabled.get().equals( "FALSE" ) )
887                    {
888                        set.add( sr );
889                    }
890                }
891            }
892            finally
893            {
894                if ( cursor != null )
895                {
896                    cursor.close();
897                }
898            }
899    
900            return set;
901        }
902    
903    
904        /* (non-Javadoc)
905         * @see org.apache.directory.server.core.schema.SchemaPartitionDao#listObjectClassDependents(org.apache.directory.shared.ldap.schema.ObjectClass)
906         */
907        public Set<ServerEntry> listObjectClassDependents( ObjectClass oc ) throws Exception
908        {
909            /*
910             * Right now the following inefficient filter is being used:
911             * 
912             * ( & 
913             *      ( | ( objectClass = metaObjectClass ) ( objectClass = metaDITContentRule ) 
914             *          ( objectClass = metaNameForm ) )
915             *      ( | ( m-oc = $oid ) ( m-aux = $oid ) ( m-supObjectClass = $oid ) )
916             * )
917             * 
918             * The reason why this is inefficient is because the or terms have large scan counts
919             * and several loops are going to be required.  For example all the objectClasses and 
920             * all the metaDITContentRules and all the metaNameForm candidates will be a massive 
921             * number.  This is probably going to be bigger than the 2nd term where a candidate 
922             * satisfies one of the terms.
923             * 
924             * The following search is better because it constrains the results better:
925             * 
926             * ( |
927             *      ( & ( objectClass = metaNameForm ) ( m-oc = $oid ) )
928             *      ( & ( objectClass = metaObjectClass ) ( m-supObjectClass = $oid ) )
929             *      ( & ( objectClass = metaDITContentRule ) ( m-aux = $oid ) )
930             * )
931             */
932    
933            Set<ServerEntry> set = new HashSet<ServerEntry>();
934            BranchNode filter = new AndNode();
935    
936            BranchNode or = new OrNode();
937            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue( MetaSchemaConstants.META_NAME_FORM_OC
938                .toLowerCase() ) ) );
939            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue( MetaSchemaConstants.META_OBJECT_CLASS_OC
940                .toLowerCase() ) ) );
941            or.addNode( new EqualityNode<String>( OBJECTCLASS_OID, new StringValue(
942                MetaSchemaConstants.META_DIT_CONTENT_RULE_OC.toLowerCase() ) ) );
943            filter.addNode( or );
944    
945            or = new OrNode();
946            or.addNode( new EqualityNode<String>( M_AUX_OID, new StringValue( oc.getOid() ) ) );
947            or.addNode( new EqualityNode<String>( M_OC_OID, new StringValue( oc.getOid() ) ) );
948            or.addNode( new EqualityNode<String>( M_SUP_OBJECT_CLASS_OID, new StringValue( oc.getOid() ) ) );
949            filter.addNode( or );
950    
951            SearchControls searchControls = new SearchControls();
952            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
953            EntryFilteringCursor cursor = null;
954    
955            try
956            {
957                SearchOperationContext searchOperationContext = new SearchOperationContext( null, partition.getSuffixDn(),
958                    filter, searchControls );
959                searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
960                
961                cursor = partition.search( searchOperationContext );
962                
963                while ( cursor.next() )
964                {
965                    set.add( cursor.get() );
966                }
967            }
968            finally
969            {
970                if ( cursor != null )
971                {
972                    cursor.close();
973                }
974            }
975    
976            return set;
977        }
978    }