blob: ce0e81a7a2108ed33f270c2994266918b5b49b8b [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.configuration;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.server.constants.ApacheSchemaConstants;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.authn.LdapPrincipal;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
import org.apache.directory.server.protocol.shared.store.LdifLoadFilter;
import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.message.AttributesImpl;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.util.StringTools;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Apache Directory Server top level.
*
* @org.apache.xbean.XBean
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$
*/
public class ApacheDS
{
private static final String WINDOWSFILE_ATTR = "windowsFilePath";
private static final String UNIXFILE_ATTR = "unixFilePath";
private static final Logger LOG = LoggerFactory.getLogger( ApacheDS.class.getName() );
private static final String LDIF_FILES_DN = "ou=loadedLdifFiles,ou=configuration,ou=system";
private static final long DEFAULT_SYNC_PERIOD_MILLIS = 20000;
private long synchPeriodMillis = DEFAULT_SYNC_PERIOD_MILLIS;
private File ldifDirectory;
private final List<LdifLoadFilter> ldifFilters = new ArrayList<LdifLoadFilter>();
private final LdapServer ldapServer;
private final LdapServer ldapsServer;
private final DirectoryService directoryService;
public ApacheDS( DirectoryService directoryService, LdapServer ldapServer, LdapServer ldapsServer )
{
this.directoryService = directoryService == null? new DefaultDirectoryService(): directoryService;
this.ldapServer = ldapServer;
this.ldapsServer = ldapsServer;
ByteBuffer.setAllocator( new SimpleByteBufferAllocator() );
ByteBuffer.setUseDirectBuffers( false );
}
public void startup() throws NamingException, IOException
{
if ( ! directoryService.isStarted() )
{
directoryService.startup();
}
loadLdifs();
if ( ldapServer != null && ! ldapServer.isStarted() )
{
ldapServer.start();
}
if ( ldapsServer != null && ! ldapsServer.isStarted() )
{
ldapsServer.start();
}
}
public boolean isStarted()
{
if ( ldapServer != null || ldapsServer != null )
{
return ( ldapServer != null && ldapServer.isStarted() )
|| ( ldapsServer != null && ldapsServer.isStarted() );
}
return directoryService.isStarted();
}
public void shutdown() throws NamingException
{
if ( ldapServer != null && ldapServer.isStarted() )
{
ldapServer.stop();
}
if ( ldapsServer != null && ldapsServer.isStarted() )
{
ldapsServer.stop();
}
directoryService.shutdown();
}
public LdapServer getLdapServer()
{
return ldapServer;
}
public LdapServer getLdapsServer()
{
return ldapsServer;
}
public DirectoryService getDirectoryService()
{
return directoryService;
}
public long getSynchPeriodMillis()
{
return synchPeriodMillis;
}
public void setSynchPeriodMillis( long synchPeriodMillis )
{
this.synchPeriodMillis = synchPeriodMillis;
}
public File getLdifDirectory()
{
if ( ldifDirectory == null )
{
return null;
}
else if ( ldifDirectory.isAbsolute() )
{
return this.ldifDirectory;
}
else
{
return new File( directoryService.getWorkingDirectory().getParent() , ldifDirectory.toString() );
}
}
public void setAllowAnonymousAccess( boolean allowAnonymousAccess )
{
this.directoryService.setAllowAnonymousAccess( allowAnonymousAccess );
if ( ldapServer != null )
{
this.ldapServer.setAllowAnonymousAccess( allowAnonymousAccess );
}
if ( ldapsServer != null )
{
this.ldapsServer.setAllowAnonymousAccess( allowAnonymousAccess );
}
}
public void setLdifDirectory( File ldifDirectory )
{
this.ldifDirectory = ldifDirectory;
}
public List<LdifLoadFilter> getLdifFilters()
{
return new ArrayList<LdifLoadFilter>( ldifFilters );
}
protected void setLdifFilters( List<LdifLoadFilter> filters )
{
this.ldifFilters.clear();
this.ldifFilters.addAll( filters );
}
// ----------------------------------------------------------------------
// From CoreContextFactory: presently in intermediate step but these
// methods will be moved to the appropriate protocol service eventually.
// This is here simply to start to remove the JNDI dependency then further
// refactoring will be needed to place these where they belong.
// ----------------------------------------------------------------------
private void ensureLdifFileBase( DirContext root )
{
Attributes entry = new AttributesImpl( SchemaConstants.OU_AT, "loadedLdifFiles", true );
entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC );
entry.get( SchemaConstants.OBJECT_CLASS_AT ).add( SchemaConstants.ORGANIZATIONAL_UNIT_OC );
try
{
root.createSubcontext( LDIF_FILES_DN, entry );
LOG.info( "Creating " + LDIF_FILES_DN );
}
catch ( NamingException e )
{
LOG.info( LDIF_FILES_DN + " exists" );
}
}
private String buildProtectedFileEntry( File ldif )
{
StringBuffer buf = new StringBuffer();
buf.append( File.separatorChar == '\\' ? WINDOWSFILE_ATTR : UNIXFILE_ATTR );
buf.append( "=" );
buf.append( StringTools.dumpHexPairs( StringTools.getBytesUtf8( getCanonical( ldif ) ) ) );
buf.append( "," );
buf.append( LDIF_FILES_DN );
return buf.toString();
}
private void addFileEntry( DirContext root, File ldif ) throws NamingException
{
String rdnAttr = File.separatorChar == '\\' ? WINDOWSFILE_ATTR : UNIXFILE_ATTR;
String oc = File.separatorChar == '\\' ? ApacheSchemaConstants.WINDOWS_FILE_OC : ApacheSchemaConstants.UNIX_FILE_OC;
Attributes entry = new AttributesImpl( rdnAttr, getCanonical( ldif ), true );
entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC );
entry.get( SchemaConstants.OBJECT_CLASS_AT ).add( oc );
root.createSubcontext( buildProtectedFileEntry( ldif ), entry );
}
private Attributes getLdifFileEntry( DirContext root, File ldif )
{
try
{
return root.getAttributes( buildProtectedFileEntry( ldif ), new String[]
{ SchemaConstants.CREATE_TIMESTAMP_AT } );
}
catch ( NamingException e )
{
return null;
}
}
private String getCanonical( File file )
{
String canonical;
try
{
canonical = file.getCanonicalPath();
}
catch ( IOException e )
{
LOG.error( "could not get canonical path", e );
return null;
}
return StringUtils.replace( canonical, "\\", "\\\\" );
}
private void loadLdifs() throws NamingException
{
// LOG and bail if property not set
if ( ldifDirectory == null )
{
LOG.info( "LDIF load directory not specified. No LDIF files will be loaded." );
return;
}
// LOG and bail if LDIF directory does not exists
if ( ! ldifDirectory.exists() )
{
LOG.warn( "LDIF load directory '" + getCanonical( ldifDirectory )
+ "' does not exist. No LDIF files will be loaded." );
return;
}
LdapPrincipal admin = new LdapPrincipal( new LdapDN( ServerDNConstants.ADMIN_SYSTEM_DN ),
AuthenticationLevel.STRONG );
DirContext root = directoryService.getJndiContext( admin );
ensureLdifFileBase( root );
// if ldif directory is a file try to load it
if ( ! ldifDirectory.isDirectory() )
{
if ( LOG.isInfoEnabled() )
{
LOG.info( "LDIF load directory '" + getCanonical( ldifDirectory )
+ "' is a file. Will attempt to load as LDIF." );
}
Attributes fileEntry = getLdifFileEntry( root, ldifDirectory );
if ( fileEntry != null )
{
String time = ( String ) fileEntry.get( SchemaConstants.CREATE_TIMESTAMP_AT ).get();
if ( LOG.isInfoEnabled() )
{
LOG.info( "Load of LDIF file '" + getCanonical( ldifDirectory )
+ "' skipped. It has already been loaded on " + time + "." );
}
return;
}
LdifFileLoader loader = new LdifFileLoader( root, ldifDirectory, ldifFilters );
loader.execute();
addFileEntry( root, ldifDirectory );
return;
}
// get all the ldif files within the directory (should be sorted alphabetically)
File[] ldifFiles = ldifDirectory.listFiles( new FileFilter()
{
public boolean accept( File pathname )
{
boolean isLdif = pathname.getName().toLowerCase().endsWith( ".ldif" );
return pathname.isFile() && pathname.canRead() && isLdif;
}
} );
// LOG and bail if we could not find any LDIF files
if ( ldifFiles == null || ldifFiles.length == 0 )
{
LOG.warn( "LDIF load directory '" + getCanonical( ldifDirectory )
+ "' does not contain any LDIF files. No LDIF files will be loaded." );
return;
}
// load all the ldif files and load each one that is loaded
for ( File ldifFile : ldifFiles )
{
Attributes fileEntry = getLdifFileEntry( root, ldifFile );
if ( fileEntry != null )
{
String time = ( String ) fileEntry.get( SchemaConstants.CREATE_TIMESTAMP_AT ).get();
LOG.info( "Load of LDIF file '" + getCanonical( ldifFile )
+ "' skipped. It has already been loaded on " + time + "." );
continue;
}
LdifFileLoader loader = new LdifFileLoader( root, ldifFile, ldifFilters );
int count = loader.execute();
LOG.info( "Loaded " + count + " entries from LDIF file '" + getCanonical( ldifFile ) + "'" );
addFileEntry( root, ldifFile );
}
}
}