blob: 7db79dc441551dd3c04c16f5534f9adacbf49faa [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
*
* https://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.ldap.client.api;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import org.apache.directory.api.asn1.util.Oid;
import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.cursor.SearchCursor;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.ldap.model.ldif.LdifReader;
import org.apache.directory.api.ldap.model.message.AbandonRequest;
import org.apache.directory.api.ldap.model.message.AddRequest;
import org.apache.directory.api.ldap.model.message.AddResponse;
import org.apache.directory.api.ldap.model.message.BindRequest;
import org.apache.directory.api.ldap.model.message.BindResponse;
import org.apache.directory.api.ldap.model.message.CompareRequest;
import org.apache.directory.api.ldap.model.message.CompareResponse;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.DeleteRequest;
import org.apache.directory.api.ldap.model.message.DeleteResponse;
import org.apache.directory.api.ldap.model.message.ExtendedRequest;
import org.apache.directory.api.ldap.model.message.ExtendedResponse;
import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
import org.apache.directory.api.ldap.model.message.ModifyRequest;
import org.apache.directory.api.ldap.model.message.ModifyResponse;
import org.apache.directory.api.ldap.model.message.SearchRequest;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.ObjectClass;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.model.schema.registries.Schema;
import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
import org.apache.directory.api.util.exception.Exceptions;
import org.junit.jupiter.api.Test;
/**
* Tests the DefaultSchemaLoader and DefaultSchemaManager with schema that is full of quirks.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class QuirkySchemaTest
{
protected static final String SCHEMA_DN = "cn=schema";
/**
* Try to load a very minimal (and correct) schema. It has just 'person' objectclass and all
* the necessary attributes, matching rules and syntaxes. Load it in strict mode.
* This test is here mostly to make sure that the test itself works.
*/
@Test
public void testLoadMinimalSchema() throws Exception
{
LdapConnection connection = createFakeConnection( "src/test/resources/schema-minimal.ldif" );
DefaultSchemaLoader loader = new DefaultSchemaLoader( connection );
Collection<Schema> allEnabled = loader.getAllEnabled();
assertEquals( 1, allEnabled.size() );
Schema schema = allEnabled.iterator().next();
assertNotNull( schema );
assertEquals( 26, schema.getContent().size() );
SchemaManager schemaManager = new DefaultSchemaManager( loader );
boolean loaded = schemaManager.loadAllEnabled();
if ( !loaded )
{
fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
}
assertTrue( schemaManager.getRegistries().getAttributeTypeRegistry().contains( "cn" ) );
ObjectClass person = schemaManager.getRegistries().getObjectClassRegistry().lookup( "person" );
assertNotNull( person );
assertEquals( 2, person.getMustAttributeTypes().size() );
assertEquals( 4, person.getMayAttributeTypes().size() );
}
/**
* Try to load a quirky schema. This schema has a lot of issues that violate the
* standards. Therefore load the schema in relaxed mode. We should be able to work
* with this schema anyway. E.g. the loader and schema manager should not die on
* null pointer or similar trivial error.
*/
@Test
public void testLoadQuirkySchema() throws Exception
{
LdapConnection connection = createFakeConnection( "src/test/resources/schema-quirky.ldif" );
DefaultSchemaLoader loader = new DefaultSchemaLoader( connection, true );
Collection<Schema> allEnabled = loader.getAllEnabled();
assertEquals( 1, allEnabled.size() );
Schema schema = allEnabled.iterator().next();
assertNotNull( schema );
SchemaManager schemaManager = new DefaultSchemaManager( loader );
boolean loaded = schemaManager.loadAllEnabledRelaxed();
if ( !loaded )
{
fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
}
assertTrue ( schemaManager.getErrors().size() > 0, "Surprisingly no errors after load" );
assertTrue( schemaManager.getRegistries().getAttributeTypeRegistry().contains( "cn" ) );
ObjectClass person = schemaManager.getRegistries().getObjectClassRegistry().lookup( "person" );
assertNotNull( person );
assertEquals( 2, person.getMustAttributeTypes().size() );
assertEquals( 5, person.getMayAttributeTypes().size() );
}
private LdapConnection createFakeConnection( final String schemaFileName )
{
return new LdapConnection()
{
@Override
public void unBind() throws LdapException
{
}
@Override
public void setTimeOut( long timeOut )
{
}
@Override
public void setSchemaManager( SchemaManager schemaManager )
{
}
@Override
public void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetecter )
{
}
@Override
public SearchCursor search( SearchRequest searchRequest ) throws LdapException
{
return null;
}
@Override
public EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes )
throws LdapException
{
return null;
}
@Override
public EntryCursor search( Dn baseDn, String filter, SearchScope scope, String... attributes ) throws LdapException
{
return null;
}
@Override
public void rename( Dn entryDn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
{
}
@Override
public void rename( String entryDn, String newRdn, boolean deleteOldRdn ) throws LdapException
{
}
@Override
public void rename( Dn entryDn, Rdn newRdn ) throws LdapException
{
}
@Override
public void rename( String entryDn, String newRdn ) throws LdapException
{
}
@Override
public void moveAndRename( String entryDn, String newDn, boolean deleteOldRdn ) throws LdapException
{
}
@Override
public void moveAndRename( Dn entryDn, Dn newDn, boolean deleteOldRdn ) throws LdapException
{
}
@Override
public void moveAndRename( String entryDn, String newDn ) throws LdapException
{
}
@Override
public void moveAndRename( Dn entryDn, Dn newDn ) throws LdapException
{
}
@Override
public void move( Dn entryDn, Dn newSuperiorDn ) throws LdapException
{
}
@Override
public void move( String entryDn, String newSuperiorDn ) throws LdapException
{
}
@Override
public ModifyDnResponse modifyDn( ModifyDnRequest modDnRequest ) throws LdapException
{
return null;
}
@Override
public ModifyResponse modify( ModifyRequest modRequest ) throws LdapException
{
return null;
}
@Override
public void modify( Entry entry, ModificationOperation modOp ) throws LdapException
{
}
@Override
public void modify( String dn, Modification... modifications ) throws LdapException
{
}
@Override
public void modify( Dn dn, Modification... modifications ) throws LdapException
{
}
@Override
public Entry lookup( String dn, Control[] controls, String... attributes ) throws LdapException
{
return lookup(new Dn(dn));
}
@Override
public Entry lookup( String dn, String... attributes ) throws LdapException
{
return lookup(new Dn(dn));
}
@Override
public Entry lookup( Dn dn, Control[] controls, String... attributes ) throws LdapException
{
return lookup(dn);
}
@Override
public Entry lookup( Dn dn, String... attributes ) throws LdapException
{
return lookup(dn);
}
@Override
public Entry lookup( String dn ) throws LdapException
{
return lookup(new Dn(dn));
}
@Override
public Entry lookup( Dn dn ) throws LdapException
{
if ( dn.isRootDse() )
{
Entry entry = new DefaultEntry( dn );
entry.add( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, SCHEMA_DN );
return entry;
}
else if ( dn.toString().equals( SCHEMA_DN ) )
{
Entry entry = loadSchemaEntry( schemaFileName );
return entry;
}
else
{
throw new UnsupportedOperationException( "Unexpected DN " + dn );
}
}
@Override
public void loadSchemaRelaxed() throws LdapException
{
}
@Override
public void loadSchema() throws LdapException
{
}
@Override
public boolean isRequestCompleted( int messageId )
{
return true;
}
@Override
public boolean isControlSupported( String controlOID ) throws LdapException
{
return true;
}
@Override
public boolean isConnected()
{
return true;
}
@Override
public boolean isAuthenticated()
{
return false;
}
@Override
public Throwable exceptionCaught()
{
return null;
}
@Override
public List<String> getSupportedControls() throws LdapException
{
return null;
}
@Override
public SchemaManager getSchemaManager()
{
return null;
}
@Override
public Entry getRootDse( String... attributes ) throws LdapException
{
return lookup( Dn.ROOT_DSE );
}
@Override
public Entry getRootDse() throws LdapException
{
return lookup( Dn.ROOT_DSE );
}
@Override
public LdapApiService getCodecService()
{
return null;
}
@Override
public BinaryAttributeDetector getBinaryAttributeDetector()
{
return null;
}
@Override
public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
{
return null;
}
@Override
public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
{
return null;
}
@Override
public ExtendedResponse extended( Oid oid ) throws LdapException
{
return null;
}
@Override
public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
{
return null;
}
@Override
public ExtendedResponse extended( String oid ) throws LdapException
{
return null;
}
@Override
public boolean exists( Dn dn ) throws LdapException
{
return false;
}
@Override
public boolean exists( String dn ) throws LdapException
{
return false;
}
@Override
public boolean doesFutureExistFor( int messageId )
{
return false;
}
@Override
public DeleteResponse delete( DeleteRequest deleteRequest ) throws LdapException
{
return null;
}
@Override
public void delete( Dn dn ) throws LdapException
{
}
@Override
public void delete( String dn ) throws LdapException
{
}
@Override
public boolean connect() throws LdapException
{
return true;
}
@Override
public CompareResponse compare( CompareRequest compareRequest ) throws LdapException
{
return null;
}
@Override
public boolean compare( Dn dn, String attributeName, byte[] value ) throws LdapException
{
return false;
}
@Override
public boolean compare( Dn dn, String attributeName, String value ) throws LdapException
{
return false;
}
@Override
public boolean compare( String dn, String attributeName, byte[] value ) throws LdapException
{
return false;
}
@Override
public boolean compare( String dn, String attributeName, String value ) throws LdapException
{
return false;
}
@Override
public void close() throws IOException
{
}
@Override
public BindResponse bind( BindRequest bindRequest ) throws LdapException
{
return null;
}
@Override
public void bind( Dn name, String credentials ) throws LdapException
{
}
@Override
public void bind( Dn name ) throws LdapException
{
}
@Override
public void bind( String name, String credentials ) throws LdapException
{
}
@Override
public void bind( String name ) throws LdapException
{
}
@Override
public void bind() throws LdapException
{
}
@Override
public void anonymousBind() throws LdapException
{
}
@Override
public AddResponse add( AddRequest addRequest ) throws LdapException
{
return null;
}
@Override
public void add( Entry entry ) throws LdapException
{
}
@Override
public void abandon( AbandonRequest abandonRequest )
{
}
@Override
public void abandon( int messageId )
{
}
@Override
public boolean compare( String dn, String attributeName, Value value ) throws LdapException
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean compare( Dn dn, String attributeName, Value value ) throws LdapException
{
// TODO Auto-generated method stub
return false;
}
@Override
public BindResponse bind( SaslRequest saslRequest ) throws LdapException
{
// TODO Auto-generated method stub
return null;
}
};
}
private Entry loadSchemaEntry( String schemaFileName )
{
LdifEntry ldifEntry = null;
try
{
InputStream in = new FileInputStream( schemaFileName );
LdifReader ldifReader = new LdifReader( in );
if (ldifReader.hasNext())
{
ldifEntry = ldifReader.next();
}
ldifReader.close();
}
catch ( IOException e )
{
throw new IllegalStateException( "IO error with " + schemaFileName , e );
}
catch (LdapException e )
{
throw new IllegalStateException( "LDAP error with " + schemaFileName , e );
}
if (ldifEntry == null)
{
throw new IllegalStateException( "No entry in LDIF " + schemaFileName );
}
return ldifEntry.getEntry();
}
}