blob: ec395e174679542679d66ca9ef2f2759b7f842a3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.core.schema;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.normalization.FilterNormalizingVisitor;
import org.apache.directory.server.core.partition.Partition;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.entry.EntryAttribute;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.shared.ldap.model.exception.LdapOtherException;
import org.apache.directory.shared.ldap.model.filter.ExprNode;
import org.apache.directory.shared.ldap.model.filter.FilterParser;
import org.apache.directory.shared.ldap.model.filter.SearchScope;
import org.apache.directory.shared.ldap.model.name.Dn;
import org.apache.directory.shared.ldap.model.name.NameComponentNormalizer;
import org.apache.directory.shared.ldap.model.schema.MutableAttributeTypeImpl;
import org.apache.directory.shared.ldap.model.schema.SchemaManager;
import org.apache.directory.shared.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
import org.apache.directory.shared.ldap.model.schema.registries.AbstractSchemaLoader;
import org.apache.directory.shared.ldap.model.schema.registries.Registries;
import org.apache.directory.shared.ldap.model.schema.registries.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A class that loads schemas from a partition.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class PartitionSchemaLoader extends AbstractSchemaLoader
{
/** static class logger */
private static final Logger LOG = LoggerFactory.getLogger( PartitionSchemaLoader.class );
private final SchemaPartitionDao dao;
private Partition partition;
/** The attributeType registry */
private SchemaManager schemaManager;
private final MutableAttributeTypeImpl cnAT;
public PartitionSchemaLoader( Partition partition, SchemaManager schemaManager ) throws Exception
{
this.partition = partition;
this.schemaManager = schemaManager;
dao = new SchemaPartitionDaoImpl( this.partition, schemaManager );
cnAT = schemaManager.getAttributeType( SchemaConstants.CN_AT );
initializeSchemas();
}
private void initializeSchemas() throws Exception
{
Dn dn = new Dn( schemaManager, SchemaConstants.OU_SCHEMA );
// Check that the ou=schema entry exists
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return;
}
LOG.debug( "Loading schemas" );
// One-level search for all schema entries
SearchOperationContext searchCtx = new SearchOperationContext( null );
searchCtx.setDn( dn );
searchCtx.setScope( SearchScope.ONELEVEL );
ExprNode filter = FilterParser.parse(schemaManager, "(objectClass=metaSchema)");
NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager );
FilterNormalizingVisitor visitor = new FilterNormalizingVisitor( ncn, schemaManager );
filter.accept( visitor );
searchCtx.setFilter( filter );
EntryFilteringCursor list = partition.search( searchCtx );
// Loop on all the schema entries
while ( list.next() )
{
Entry entry = list.get();
Schema schema = getSchema( entry );
schemaMap.put( schema.getSchemaName(), schema );
}
}
/**
* Gets the base Dn for an Schema Object
*/
private Dn getBaseDN( String path, Schema schema ) throws LdapInvalidDnException
{
Dn dn = new Dn( schemaManager, path, "cn=" + schema.getSchemaName(), SchemaConstants.OU_SCHEMA );
return dn;
}
/**
* Lists the names of the schemas that depend on the schema name provided.
*
* @param schemaName the name of the schema to find dependents for
* @return a set of schemas (String names) that depend on the schema
* @throws Exception if there are problems searching the schema partition
*/
public Set<String> listDependentSchemaNames( String schemaName ) throws Exception
{
Set<String> dependees = new HashSet<String>();
Set<Entry> results = dao.listSchemaDependents( schemaName );
if ( results.isEmpty() )
{
return dependees;
}
for ( Entry sr : results )
{
EntryAttribute cn = sr.get( cnAT );
dependees.add( cn.getString() );
}
return dependees;
}
/**
* Lists the names of the enabled schemas that depend on the schema name
* provided.
*
* @param schemaName the name of the schema to find dependents for
* @return a set of enabled schemas (String names) that depend on the schema
* @throws Exception if there are problems searching the schema partition
*/
public Set<String> listEnabledDependentSchemaNames( String schemaName ) throws Exception
{
Set<String> dependees = new HashSet<String>();
Set<Entry> results = dao.listEnabledSchemaDependents( schemaName );
if ( results.isEmpty() )
{
return dependees;
}
for ( Entry sr : results )
{
EntryAttribute cn = sr.get( cnAT );
dependees.add( cn.getString() );
}
return dependees;
}
public Map<String, Schema> getSchemas() throws Exception
{
return dao.getSchemas();
}
public Set<String> getSchemaNames() throws Exception
{
return dao.getSchemaNames();
}
public Schema getSchema( String schemaName )
{
try
{
return dao.getSchema( schemaName );
}
catch ( Exception e )
{
// TODO fixme
return null;
}
}
public final void load( Schema schema, Registries targetRegistries, boolean isDepLoad ) throws Exception
{
// if we're loading a dependency and it has not been enabled on
// disk then enable it on disk before we proceed to load it
if ( schema.isDisabled() && isDepLoad )
{
dao.enableSchema( schema.getSchemaName() );
}
if ( targetRegistries.isSchemaLoaded( schema.getSchemaName() ) )
{
LOG.debug( "schema {} already seems to be loaded", schema.getSchemaName() );
return;
}
LOG.debug( "loading {} schema ...", schema.getSchemaName() );
loadComparators( schema );
loadNormalizers( schema );
loadSyntaxCheckers( schema );
loadSyntaxes( schema );
loadMatchingRules( schema );
loadAttributeTypes( schema );
loadObjectClasses( schema );
loadMatchingRuleUses( schema );
loadDitContentRules( schema );
loadNameForms( schema );
// order does matter here so some special trickery is needed
// we cannot load a DSR before the DSRs it depends on are loaded?
// TODO need to confirm this ( or we must make the class for this and use deferred
// resolution until everything is available?
loadDitStructureRules( schema );
notifyListenerOrRegistries( schema, targetRegistries );
}
/**
* {@inheritDoc}
*/
public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException
{
List<Entry> attributeTypeList = new ArrayList<Entry>();
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.ATTRIBUTES_TYPE_PATH, schema );
// Check that we don't have an entry in the Dit for this schema
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
// No : get out, no AttributeType to load
return attributeTypeList;
}
LOG.debug( "{} schema: loading attributeTypes", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
// Loop on all the AttributeTypes and add them to the list
while ( list.next() )
{
Entry result = list.get();
attributeTypeList.add( result );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return attributeTypeList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadComparators( Schema... schemas ) throws LdapException
{
List<Entry> comparatorList = new ArrayList<Entry>();
if ( schemas == null )
{
return comparatorList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.COMPARATORS_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return comparatorList;
}
LOG.debug( "{} schema: loading comparators", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
ClonedServerEntry entry = list.get();
comparatorList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return comparatorList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException
{
LOG.error( I18n.err( I18n.ERR_86 ) );
List<Entry> ditContentRuleList = new ArrayList<Entry>();
return ditContentRuleList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException
{
LOG.error( I18n.err( I18n.ERR_87 ) );
List<Entry> ditStructureRuleList = new ArrayList<Entry>();
return ditStructureRuleList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException
{
List<Entry> matchingRuleList = new ArrayList<Entry>();
if ( schemas == null )
{
return matchingRuleList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.MATCHING_RULES_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return matchingRuleList;
}
LOG.debug( "{} schema: loading matchingRules", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
Entry entry = list.get();
matchingRuleList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return matchingRuleList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException
{
LOG.error( I18n.err( I18n.ERR_88 ) );
List<Entry> matchingRuleUsesList = new ArrayList<Entry>();
return matchingRuleUsesList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadNameForms( Schema... schemas ) throws LdapException
{
LOG.error( I18n.err( I18n.ERR_89 ) );
List<Entry> nameFormList = new ArrayList<Entry>();
return nameFormList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException
{
List<Entry> normalizerList = new ArrayList<Entry>();
if ( schemas == null )
{
return normalizerList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.NORMALIZERS_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return normalizerList;
}
LOG.debug( "{} schema: loading normalizers", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
ClonedServerEntry entry = list.get();
normalizerList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return normalizerList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException
{
List<Entry> objectClassList = new ArrayList<Entry>();
if ( schemas == null )
{
return objectClassList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.OBJECT_CLASSES_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return objectClassList;
}
LOG.debug( "{} schema: loading objectClasses", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
ClonedServerEntry entry = list.get();
objectClassList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return objectClassList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException
{
List<Entry> syntaxList = new ArrayList<Entry>();
if ( schemas == null )
{
return syntaxList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.SYNTAXES_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return syntaxList;
}
LOG.debug( "{} schema: loading syntaxes", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
Entry entry = list.get();
syntaxList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return syntaxList;
}
/**
* {@inheritDoc}
*/
public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException
{
List<Entry> syntaxCheckerList = new ArrayList<Entry>();
if ( schemas == null )
{
return syntaxCheckerList;
}
for ( Schema schema : schemas )
{
Dn dn = getBaseDN( SchemaConstants.SYNTAX_CHECKERS_PATH, schema );
if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
{
return syntaxCheckerList;
}
LOG.debug( "{} schema: loading syntaxCsheckers", schema.getSchemaName() );
EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );
try
{
while ( list.next() )
{
Entry entry = list.get();
syntaxCheckerList.add( entry );
}
}
catch ( Exception e )
{
throw new LdapOtherException( e.getMessage() );
}
}
return syntaxCheckerList;
}
/**
* @return the dao
*/
public SchemaPartitionDao getDao()
{
return dao;
}
}