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 021 package org.apache.directory.server.config; 022 023 024 import java.io.File; 025 import java.io.FilenameFilter; 026 import java.util.ArrayList; 027 import java.util.HashMap; 028 import java.util.HashSet; 029 import java.util.Iterator; 030 import java.util.List; 031 import java.util.Map; 032 import java.util.Set; 033 import java.util.TreeSet; 034 035 import javax.naming.directory.SearchControls; 036 037 import org.apache.directory.server.core.DefaultDirectoryService; 038 import org.apache.directory.server.core.DirectoryService; 039 import org.apache.directory.server.core.changelog.ChangeLog; 040 import org.apache.directory.server.core.changelog.DefaultChangeLog; 041 import org.apache.directory.server.core.entry.ClonedServerEntry; 042 import org.apache.directory.server.core.interceptor.Interceptor; 043 import org.apache.directory.server.core.journal.DefaultJournal; 044 import org.apache.directory.server.core.journal.DefaultJournalStore; 045 import org.apache.directory.server.core.journal.Journal; 046 import org.apache.directory.server.core.journal.JournalStore; 047 import org.apache.directory.server.core.partition.Partition; 048 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex; 049 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition; 050 import org.apache.directory.server.core.partition.ldif.LdifPartition; 051 import org.apache.directory.server.dhcp.service.DhcpService; 052 import org.apache.directory.server.dhcp.service.StoreBasedDhcpService; 053 import org.apache.directory.server.dhcp.store.DhcpStore; 054 import org.apache.directory.server.dhcp.store.SimpleDhcpStore; 055 import org.apache.directory.server.dns.DnsServer; 056 import org.apache.directory.server.i18n.I18n; 057 import org.apache.directory.server.integration.http.HttpServer; 058 import org.apache.directory.server.integration.http.WebApp; 059 import org.apache.directory.server.kerberos.kdc.KdcServer; 060 import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType; 061 import org.apache.directory.server.ldap.LdapServer; 062 import org.apache.directory.server.ntp.NtpServer; 063 import org.apache.directory.server.protocol.shared.transport.TcpTransport; 064 import org.apache.directory.server.protocol.shared.transport.Transport; 065 import org.apache.directory.server.protocol.shared.transport.UdpTransport; 066 import org.apache.directory.server.xdbm.ForwardIndexEntry; 067 import org.apache.directory.server.xdbm.Index; 068 import org.apache.directory.server.xdbm.IndexCursor; 069 import org.apache.directory.server.xdbm.search.SearchEngine; 070 import org.apache.directory.shared.ldap.NotImplementedException; 071 import org.apache.directory.shared.ldap.entry.StringValue; 072 import org.apache.directory.shared.ldap.entry.Entry; 073 import org.apache.directory.shared.ldap.entry.EntryAttribute; 074 import org.apache.directory.shared.ldap.entry.ServerEntry; 075 import org.apache.directory.shared.ldap.entry.Value; 076 import org.apache.directory.shared.ldap.filter.EqualityNode; 077 import org.apache.directory.shared.ldap.filter.PresenceNode; 078 import org.apache.directory.shared.ldap.ldif.LdifEntry; 079 import org.apache.directory.shared.ldap.ldif.LdifReader; 080 import org.apache.directory.shared.ldap.message.AliasDerefMode; 081 import org.apache.directory.shared.ldap.name.DN; 082 import org.apache.directory.shared.ldap.schema.SchemaManager; 083 import org.slf4j.Logger; 084 import org.slf4j.LoggerFactory; 085 086 087 /** 088 * A class used for reading the configuration present in a Partition 089 * and instantiate the necessary objects like DirectoryService, Interceptors etc. 090 * 091 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 092 * @version $Rev$, $Date$ 093 */ 094 public class ConfigPartitionReader 095 { 096 private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionReader.class ); 097 098 /** the partition which holds the configuration data */ 099 private LdifPartition configPartition; 100 101 /** the search engine of the partition */ 102 private SearchEngine<ServerEntry, Long> se; 103 104 /** the schema manager set in the config partition */ 105 private SchemaManager schemaManager; 106 107 /** the parent directory of the config partition's working directory */ 108 private File workDir; 109 110 /** LDIF file filter */ 111 private FilenameFilter ldifFilter = new FilenameFilter() 112 { 113 public boolean accept( File file, String name ) 114 { 115 if ( file.isDirectory() ) 116 { 117 return true; 118 } 119 120 return file.getName().toLowerCase().endsWith( ".ldif" ); 121 } 122 }; 123 124 125 /** 126 * 127 * Creates a new instance of ConfigPartitionReader. 128 * 129 * @param configPartition the non null config partition 130 */ 131 public ConfigPartitionReader( LdifPartition configPartition ) 132 { 133 if ( configPartition == null ) 134 { 135 throw new IllegalArgumentException( I18n.err( I18n.ERR_503 ) ); 136 } 137 138 if ( !configPartition.isInitialized() ) 139 { 140 throw new IllegalStateException( I18n.err( I18n.ERR_504 ) ); 141 } 142 143 this.configPartition = configPartition; 144 se = configPartition.getSearchEngine(); 145 this.schemaManager = configPartition.getSchemaManager(); 146 workDir = configPartition.getPartitionDir().getParentFile(); 147 } 148 149 150 /** 151 * reads the LDAP server configuration and instantiates without setting a DirectoryService 152 * 153 * @return the LdapServer instance without a DirectoryService 154 * @throws Exception 155 */ 156 public LdapServer getLdapServer() throws Exception 157 { 158 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( "ads-ldapServer" ) ); 159 SearchControls controls = new SearchControls(); 160 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 161 162 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 163 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 164 165 if ( !cursor.next() ) 166 { 167 LOG.warn( "No LDAP server was configured under the DN {}", configPartition.getSuffixDn() ); 168 return null; 169 } 170 171 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 172 .get(); 173 cursor.close(); 174 175 ClonedServerEntry ldapServerEntry = configPartition.lookup( forwardEntry.getId() ); 176 LOG.debug( "LDAP Server Entry {}", ldapServerEntry ); 177 178 if ( !isEnabled( ldapServerEntry ) ) 179 { 180 return null; 181 } 182 183 LdapServer server = new LdapServer(); 184 server.setServiceId( getString( "ads-serverId", ldapServerEntry ) ); 185 186 DN transportsDN = new DN( getString( "ads-transports", ldapServerEntry ) ); 187 transportsDN.normalize( schemaManager.getNormalizerMapping() ); 188 Transport[] transports = getTransports( transportsDN ); 189 server.setTransports( transports ); 190 191 return server; 192 } 193 194 195 public KdcServer getKdcServer() throws Exception 196 { 197 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( 198 "ads-kerberosServer" ) ); 199 SearchControls controls = new SearchControls(); 200 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 201 202 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 203 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 204 205 if ( !cursor.next() ) 206 { 207 LOG.warn( "No kerberos server was configured under the DN {}", configPartition.getSuffixDn() ); 208 return null; 209 } 210 211 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 212 .get(); 213 cursor.close(); 214 215 ClonedServerEntry kdcEntry = configPartition.lookup( forwardEntry.getId() ); 216 LOG.debug( "kerberos server entry {}", kdcEntry ); 217 218 if ( !isEnabled( kdcEntry ) ) 219 { 220 return null; 221 } 222 223 KdcServer kdcServer = new KdcServer(); 224 225 kdcServer.setServiceId( getString( "ads-serverId", kdcEntry ) ); 226 227 DN transportsDN = new DN( getString( "ads-transports", kdcEntry ) ); 228 transportsDN.normalize( schemaManager.getNormalizerMapping() ); 229 Transport[] transports = getTransports( transportsDN ); 230 kdcServer.setTransports( transports ); 231 232 // MAY attributes 233 EntryAttribute clockSkewAttr = kdcEntry.get( "ads-krbAllowableClockSkew" ); 234 235 if ( clockSkewAttr != null ) 236 { 237 kdcServer.setAllowableClockSkew( Long.parseLong( clockSkewAttr.getString() ) ); 238 } 239 240 EntryAttribute encryptionTypeAttr = kdcEntry.get( "ads-krbEncryptionTypes" ); 241 242 if ( encryptionTypeAttr != null ) 243 { 244 EncryptionType[] encryptionTypes = new EncryptionType[encryptionTypeAttr.size()]; 245 Iterator<Value<?>> itr = encryptionTypeAttr.getAll(); 246 int count = 0; 247 248 while ( itr.hasNext() ) 249 { 250 Value<?> val = itr.next(); 251 encryptionTypes[count++] = EncryptionType.getByName( val.getString() ); 252 } 253 254 kdcServer.setEncryptionTypes( encryptionTypes ); 255 } 256 257 EntryAttribute emptyAddrAttr = kdcEntry.get( "ads-krbEmptyAddressesAllowed" ); 258 259 if ( emptyAddrAttr != null ) 260 { 261 kdcServer.setEmptyAddressesAllowed( Boolean.parseBoolean( emptyAddrAttr.getString() ) ); 262 } 263 264 EntryAttribute fwdAllowedAttr = kdcEntry.get( "ads-krbForwardableAllowed" ); 265 266 if ( fwdAllowedAttr != null ) 267 { 268 kdcServer.setForwardableAllowed( Boolean.parseBoolean( fwdAllowedAttr.getString() ) ); 269 } 270 271 EntryAttribute paEncTmstpAttr = kdcEntry.get( "ads-krbPaEncTimestampRequired" ); 272 273 if ( paEncTmstpAttr != null ) 274 { 275 kdcServer.setPaEncTimestampRequired( Boolean.parseBoolean( paEncTmstpAttr.getString() ) ); 276 } 277 278 EntryAttribute posdtAllowedAttr = kdcEntry.get( "ads-krbPostdatedAllowed" ); 279 280 if ( posdtAllowedAttr != null ) 281 { 282 kdcServer.setPostdatedAllowed( Boolean.parseBoolean( posdtAllowedAttr.getString() ) ); 283 } 284 285 EntryAttribute prxyAllowedAttr = kdcEntry.get( "ads-krbProxiableAllowed" ); 286 287 if ( prxyAllowedAttr != null ) 288 { 289 kdcServer.setProxiableAllowed( Boolean.parseBoolean( prxyAllowedAttr.getString() ) ); 290 } 291 292 EntryAttribute rnwAllowedAttr = kdcEntry.get( "ads-krbRenewableAllowed" ); 293 294 if ( rnwAllowedAttr != null ) 295 { 296 kdcServer.setRenewableAllowed( Boolean.parseBoolean( rnwAllowedAttr.getString() ) ); 297 } 298 299 EntryAttribute kdcPrncplAttr = kdcEntry.get( "ads-krbKdcPrincipal" ); 300 301 if ( kdcPrncplAttr != null ) 302 { 303 kdcServer.setKdcPrincipal( kdcPrncplAttr.getString() ); 304 } 305 306 EntryAttribute maxRnwLfTimeAttr = kdcEntry.get( "ads-krbMaximumRenewableLifetime" ); 307 308 if ( maxRnwLfTimeAttr != null ) 309 { 310 kdcServer.setMaximumRenewableLifetime( Long.parseLong( maxRnwLfTimeAttr.getString() ) ); 311 } 312 313 EntryAttribute maxTcktLfTimeAttr = kdcEntry.get( "ads-krbMaximumTicketLifetime" ); 314 315 if ( maxTcktLfTimeAttr != null ) 316 { 317 kdcServer.setMaximumTicketLifetime( Long.parseLong( maxTcktLfTimeAttr.getString() ) ); 318 } 319 320 EntryAttribute prmRealmAttr = kdcEntry.get( "ads-krbPrimaryRealm" ); 321 322 if ( prmRealmAttr != null ) 323 { 324 kdcServer.setPrimaryRealm( prmRealmAttr.getString() ); 325 } 326 327 EntryAttribute bdyCkhsmVerifyAttr = kdcEntry.get( "ads-krbBodyChecksumVerified" ); 328 329 if ( bdyCkhsmVerifyAttr != null ) 330 { 331 kdcServer.setBodyChecksumVerified( Boolean.parseBoolean( bdyCkhsmVerifyAttr.getString() ) ); 332 } 333 334 return kdcServer; 335 } 336 337 338 public DnsServer getDnsServer() throws Exception 339 { 340 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( "ads-dnsServer" ) ); 341 SearchControls controls = new SearchControls(); 342 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 343 344 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 345 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 346 347 if ( !cursor.next() ) 348 { 349 LOG.warn( "No DNS server was configured under the DN {}", configPartition.getSuffixDn() ); 350 return null; 351 } 352 353 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 354 .get(); 355 cursor.close(); 356 357 ClonedServerEntry dnsEntry = configPartition.lookup( forwardEntry.getId() ); 358 LOG.debug( "DNS server entry {}", dnsEntry ); 359 360 if ( !isEnabled( dnsEntry ) ) 361 { 362 return null; 363 } 364 365 DnsServer dnsServer = new DnsServer(); 366 367 dnsServer.setServiceId( getString( "ads-serverId", dnsEntry ) ); 368 369 DN transportsDN = new DN( getString( "ads-transports", dnsEntry ) ); 370 transportsDN.normalize( schemaManager.getNormalizerMapping() ); 371 Transport[] transports = getTransports( transportsDN ); 372 dnsServer.setTransports( transports ); 373 374 return dnsServer; 375 } 376 377 378 //TODO making this method invisible cause there is no DhcpServer exists as of now 379 private DhcpService getDhcpServer() throws Exception 380 { 381 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( "ads-dhcpServer" ) ); 382 SearchControls controls = new SearchControls(); 383 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 384 385 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 386 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 387 388 if ( !cursor.next() ) 389 { 390 LOG.warn( "No DHCP server was configured under the DN {}", configPartition.getSuffixDn() ); 391 return null; 392 } 393 394 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 395 .get(); 396 cursor.close(); 397 398 ClonedServerEntry dhcpEntry = configPartition.lookup( forwardEntry.getId() ); 399 LOG.debug( "DHCP server entry {}", dhcpEntry ); 400 401 if ( !isEnabled( dhcpEntry ) ) 402 { 403 return null; 404 } 405 406 DhcpStore dhcpStore = new SimpleDhcpStore(); 407 DhcpService dhcpService = new StoreBasedDhcpService( dhcpStore ); 408 409 return dhcpService; 410 } 411 412 413 public NtpServer getNtpServer() throws Exception 414 { 415 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( "ads-ntpServer" ) ); 416 SearchControls controls = new SearchControls(); 417 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 418 419 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 420 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 421 422 if ( !cursor.next() ) 423 { 424 LOG.warn( "No NTP server was configured under the DN {}", configPartition.getSuffixDn() ); 425 return null; 426 } 427 428 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 429 .get(); 430 cursor.close(); 431 432 ClonedServerEntry ntpEntry = configPartition.lookup( forwardEntry.getId() ); 433 LOG.debug( "NTP server entry {}", ntpEntry ); 434 435 if ( !isEnabled( ntpEntry ) ) 436 { 437 return null; 438 } 439 440 NtpServer ntpServer = new NtpServer(); 441 442 ntpServer.setServiceId( getString( "ads-serverId", ntpEntry ) ); 443 444 DN transportsDN = new DN( getString( "ads-transports", ntpEntry ) ); 445 transportsDN.normalize( schemaManager.getNormalizerMapping() ); 446 Transport[] transports = getTransports( transportsDN ); 447 ntpServer.setTransports( transports ); 448 449 return ntpServer; 450 } 451 452 453 public HttpServer getHttpServer() throws Exception 454 { 455 EqualityNode<String> filter = new EqualityNode<String>( "objectClass", new StringValue( "ads-httpServer" ) ); 456 SearchControls controls = new SearchControls(); 457 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 458 459 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 460 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 461 462 if ( !cursor.next() ) 463 { 464 LOG.warn( "No HTTP server was configured under the DN {}", configPartition.getSuffixDn() ); 465 return null; 466 } 467 468 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 469 .get(); 470 cursor.close(); 471 472 ClonedServerEntry httpEntry = configPartition.lookup( forwardEntry.getId() ); 473 LOG.debug( "HTTP server entry {}", httpEntry ); 474 475 if ( !isEnabled( httpEntry ) ) 476 { 477 return null; 478 } 479 480 HttpServer httpServer = new HttpServer(); 481 482 EntryAttribute portAttr = httpEntry.get( "ads-systemPort" ); 483 484 if ( portAttr != null ) 485 { 486 httpServer.setPort( Integer.parseInt( portAttr.getString() ) ); 487 } 488 489 EntryAttribute confFileAttr = httpEntry.get( "ads-httpConfFile" ); 490 491 if ( confFileAttr != null ) 492 { 493 httpServer.setConfFile( confFileAttr.getString() ); 494 } 495 496 EntryAttribute webAppsAttr = httpEntry.get( "ads-httpWebApps" ); 497 498 if ( webAppsAttr != null ) 499 { 500 DN webAppsDN = new DN( webAppsAttr.getString() ); 501 webAppsDN.normalize( schemaManager.getNormalizerMapping() ); 502 503 Set<WebApp> webApps = getWebApps( webAppsDN ); 504 httpServer.setWebApps( webApps ); 505 } 506 507 return httpServer; 508 } 509 510 511 /** 512 * 513 * instantiates a DirectoryService based on the configuration present in the partition 514 * 515 * @throws Exception 516 */ 517 public DirectoryService getDirectoryService() throws Exception 518 { 519 520 PresenceNode filter = new PresenceNode( "ads-directoryServiceId" ); 521 SearchControls controls = new SearchControls(); 522 controls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 523 524 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( configPartition.getSuffixDn(), 525 AliasDerefMode.NEVER_DEREF_ALIASES, filter, controls ); 526 527 if ( !cursor.next() ) 528 { 529 // the DirectoryService is mandatory so throwing exception 530 throw new Exception( "No directoryService instance was configured under the DN " 531 + configPartition.getSuffixDn() ); 532 } 533 534 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 535 .get(); 536 cursor.close(); 537 538 ClonedServerEntry dsEntry = configPartition.lookup( forwardEntry.getId() ); 539 540 LOG.debug( "directory service entry {}", dsEntry ); 541 542 DirectoryService dirService = new DefaultDirectoryService(); 543 // MUST attributes 544 dirService.setInstanceId( getString( "ads-directoryServiceId", dsEntry ) ); 545 dirService.setReplicaId( getInt( "ads-dsReplicaId", dsEntry ) ); 546 547 DN interceptorsDN = new DN( dsEntry.get( "ads-dsInterceptors" ).getString() ); 548 interceptorsDN.normalize( configPartition.getSchemaManager().getNormalizerMapping() ); 549 List<Interceptor> interceptors = getInterceptors( interceptorsDN ); 550 dirService.setInterceptors( interceptors ); 551 552 DN partitionsDN = new DN( dsEntry.get( "ads-dsPartitions" ).getString() ); 553 partitionsDN.normalize( configPartition.getSchemaManager().getNormalizerMapping() ); 554 555 Map<String, Partition> partitions = getPartitions( partitionsDN ); 556 557 Partition systemPartition = partitions.remove( "system" ); 558 559 if ( systemPartition == null ) 560 { 561 throw new Exception( I18n.err( I18n.ERR_505 ) ); 562 } 563 564 dirService.setSystemPartition( systemPartition ); 565 dirService.setPartitions( new HashSet<Partition>( partitions.values() ) ); 566 567 // MAY attributes 568 EntryAttribute acEnabledAttr = dsEntry.get( "ads-dsAccessControlEnabled" ); 569 570 if ( acEnabledAttr != null ) 571 { 572 dirService.setAccessControlEnabled( Boolean.parseBoolean( acEnabledAttr.getString() ) ); 573 } 574 575 EntryAttribute anonAccessAttr = dsEntry.get( "ads-dsAllowAnonymousAccess" ); 576 577 if ( anonAccessAttr != null ) 578 { 579 dirService.setAllowAnonymousAccess( Boolean.parseBoolean( anonAccessAttr.getString() ) ); 580 } 581 582 EntryAttribute changeLogAttr = dsEntry.get( "ads-dsChangeLog" ); 583 584 if ( changeLogAttr != null ) 585 { 586 DN clDN = new DN( changeLogAttr.getString() ); 587 clDN.normalize( schemaManager.getNormalizerMapping() ); 588 ChangeLog cl = getChangeLog( clDN ); 589 dirService.setChangeLog( cl ); 590 } 591 592 EntryAttribute denormAttr = dsEntry.get( "ads-dsDenormalizeOpAttrsEnabled" ); 593 594 if ( denormAttr != null ) 595 { 596 dirService.setDenormalizeOpAttrsEnabled( Boolean.parseBoolean( denormAttr.getString() ) ); 597 } 598 599 EntryAttribute journalAttr = dsEntry.get( "ads-dsJournal" ); 600 601 if ( journalAttr != null ) 602 { 603 DN journalDN = new DN( journalAttr.getString() ); 604 journalDN.normalize( schemaManager.getNormalizerMapping() ); 605 dirService.setJournal( getJournal( journalDN ) ); 606 } 607 608 EntryAttribute maxPduAttr = dsEntry.get( "ads-dsMaxPDUSize" ); 609 610 if ( maxPduAttr != null ) 611 { 612 dirService.setMaxPDUSize( Integer.parseInt( maxPduAttr.getString() ) ); 613 } 614 615 EntryAttribute passwordHidAttr = dsEntry.get( "ads-dsPasswordHidden" ); 616 617 if ( passwordHidAttr != null ) 618 { 619 dirService.setPasswordHidden( Boolean.parseBoolean( passwordHidAttr.getString() ) ); 620 } 621 622 EntryAttribute replAttr = dsEntry.get( "ads-dsReplication" ); 623 624 if ( replAttr != null ) 625 { 626 // configure replication 627 } 628 629 EntryAttribute syncPeriodAttr = dsEntry.get( "ads-dsSyncPeriodMillis" ); 630 631 if ( syncPeriodAttr != null ) 632 { 633 // FIXME the DirectoryService interface doesn't have this setter 634 //dirService.setSyncPeriodMillis( Long.parseLong( syncPeriodAttr.getString() ) ); 635 } 636 637 EntryAttribute testEntryAttr = dsEntry.get( "ads-dsTestEntries" ); 638 639 if ( testEntryAttr != null ) 640 { 641 String entryFilePath = testEntryAttr.getString(); 642 dirService.setTestEntries( getTestEntries( entryFilePath ) ); 643 } 644 645 if ( !isEnabled( dsEntry ) ) 646 { 647 // will only be useful if we ever allow more than one DS to be configured and 648 // switch between them 649 // decide which one to use based on this flag 650 } 651 652 return dirService; 653 } 654 655 656 /** 657 * reads the Interceptor configuration and instantiates them in the order specified 658 * 659 * @param interceptorsDN the DN under which interceptors are configured 660 * @return a list of instantiated Interceptor objects 661 * @throws Exception 662 */ 663 private List<Interceptor> getInterceptors( DN interceptorsDN ) throws Exception 664 { 665 PresenceNode filter = new PresenceNode( "ads-interceptorId" ); 666 SearchControls controls = new SearchControls(); 667 controls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 668 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( interceptorsDN, AliasDerefMode.NEVER_DEREF_ALIASES, 669 filter, controls ); 670 671 Set<InterceptorConfig> set = new TreeSet<InterceptorConfig>(); 672 673 while ( cursor.next() ) 674 { 675 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 676 .get(); 677 ServerEntry interceptorEntry = configPartition.lookup( forwardEntry.getId() ); 678 679 String id = getString( "ads-interceptorId", interceptorEntry ); 680 String fqcn = getString( "ads-interceptorClassName", interceptorEntry ); 681 int order = getInt( "ads-interceptorOrder", interceptorEntry ); 682 683 InterceptorConfig intConfig = new InterceptorConfig( id, fqcn, order ); 684 set.add( intConfig ); 685 } 686 687 cursor.close(); 688 689 List<Interceptor> interceptors = new ArrayList<Interceptor>(); 690 691 for ( InterceptorConfig iconfig : set ) 692 { 693 try 694 { 695 LOG.debug( "loading the interceptor class {} and instantiating", iconfig.getFqcn() ); 696 Interceptor ic = ( Interceptor ) Class.forName( iconfig.getFqcn() ).newInstance(); 697 interceptors.add( ic ); 698 } 699 catch ( Exception e ) 700 { 701 throw e; 702 } 703 } 704 705 return interceptors; 706 } 707 708 709 private Map<String, Partition> getPartitions( DN partitionsDN ) throws Exception 710 { 711 PresenceNode filter = new PresenceNode( "ads-partitionId" ); 712 SearchControls controls = new SearchControls(); 713 controls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 714 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( partitionsDN, AliasDerefMode.NEVER_DEREF_ALIASES, 715 filter, controls ); 716 717 Map<String, Partition> partitions = new HashMap<String, Partition>(); 718 719 while ( cursor.next() ) 720 { 721 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 722 .get(); 723 ServerEntry partitionEntry = configPartition.lookup( forwardEntry.getId() ); 724 725 if ( !isEnabled( partitionEntry ) ) 726 { 727 continue; 728 } 729 EntryAttribute ocAttr = partitionEntry.get( "objectClass" ); 730 731 if ( ocAttr.contains( "ads-jdbmPartition" ) ) 732 { 733 JdbmPartition partition = getJdbmPartition( partitionEntry ); 734 partitions.put( partition.getId(), partition ); 735 } 736 else 737 { 738 throw new NotImplementedException( I18n.err( I18n.ERR_506 ) ); 739 } 740 } 741 742 cursor.close(); 743 744 return partitions; 745 } 746 747 748 private JdbmPartition getJdbmPartition( ServerEntry partitionEntry ) throws Exception 749 { 750 JdbmPartition partition = new JdbmPartition(); 751 partition.setSchemaManager( schemaManager ); 752 753 partition.setId( getString( "ads-partitionId", partitionEntry ) ); 754 partition.setPartitionDir( new File( workDir, partition.getId() ) ); 755 756 partition.setSuffix( getString( "ads-partitionSuffix", partitionEntry ) ); 757 758 EntryAttribute cacheAttr = partitionEntry.get( "ads-partitionCacheSize" ); 759 760 if ( cacheAttr != null ) 761 { 762 partition.setCacheSize( Integer.parseInt( cacheAttr.getString() ) ); 763 } 764 765 EntryAttribute optimizerAttr = partitionEntry.get( "ads-jdbmPartitionOptimizerEnabled" ); 766 767 if ( optimizerAttr != null ) 768 { 769 partition.setOptimizerEnabled( Boolean.parseBoolean( optimizerAttr.getString() ) ); 770 } 771 772 EntryAttribute syncAttr = partitionEntry.get( "ads-partitionSyncOnWrite" ); 773 774 if ( syncAttr != null ) 775 { 776 partition.setSyncOnWrite( Boolean.parseBoolean( syncAttr.getString() ) ); 777 } 778 779 String indexesDN = partitionEntry.get( "ads-partitionIndexedAttributes" ).getString(); 780 781 Set<Index<?, ServerEntry, Long>> indexedAttributes = getIndexes( new DN( indexesDN ) ); 782 partition.setIndexedAttributes( indexedAttributes ); 783 784 return partition; 785 } 786 787 788 private Set<Index<?, ServerEntry, Long>> getIndexes( DN indexesDN ) throws Exception 789 { 790 PresenceNode filter = new PresenceNode( "ads-indexAttributeId" ); 791 SearchControls controls = new SearchControls(); 792 controls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 793 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( indexesDN, AliasDerefMode.NEVER_DEREF_ALIASES, filter, 794 controls ); 795 796 Set<Index<?, ServerEntry, Long>> indexes = new HashSet<Index<?, ServerEntry, Long>>(); 797 798 while ( cursor.next() ) 799 { 800 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 801 .get(); 802 ServerEntry indexEntry = configPartition.lookup( forwardEntry.getId() ); 803 804 if ( !isEnabled( indexEntry ) ) 805 { 806 continue; 807 } 808 809 EntryAttribute ocAttr = indexEntry.get( "objectClass" ); 810 811 if ( ocAttr.contains( "ads-jdbmIndex" ) ) 812 { 813 indexes.add( getJdbmIndex( indexEntry ) ); 814 } 815 else 816 { 817 throw new NotImplementedException( I18n.err( I18n.ERR_506 ) ); 818 } 819 } 820 821 return indexes; 822 } 823 824 825 private JdbmIndex<?, ServerEntry> getJdbmIndex( ServerEntry indexEntry ) throws Exception 826 { 827 JdbmIndex<String, ServerEntry> index = new JdbmIndex<String, ServerEntry>(); 828 index.setAttributeId( getString( "ads-indexAttributeId", indexEntry ) ); 829 EntryAttribute cacheAttr = indexEntry.get( "ads-indexCacheSize" ); 830 831 if ( cacheAttr != null ) 832 { 833 index.setCacheSize( Integer.parseInt( cacheAttr.getString() ) ); 834 } 835 836 return index; 837 } 838 839 840 private Transport[] getTransports( DN transportsDN ) throws Exception 841 { 842 PresenceNode filter = new PresenceNode( "ads-transportId" ); 843 SearchControls controls = new SearchControls(); 844 controls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 845 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( transportsDN, AliasDerefMode.NEVER_DEREF_ALIASES, 846 filter, controls ); 847 848 List<Transport> transports = new ArrayList<Transport>(); 849 850 while ( cursor.next() ) 851 { 852 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 853 .get(); 854 ServerEntry transportEntry = configPartition.lookup( forwardEntry.getId() ); 855 856 if ( !isEnabled( transportEntry ) ) 857 { 858 continue; 859 } 860 861 transports.add( getTransport( transportEntry ) ); 862 } 863 864 return transports.toArray( new Transport[] 865 {} ); 866 } 867 868 869 private Transport getTransport( Entry transportEntry ) throws Exception 870 { 871 Transport transport = null; 872 873 EntryAttribute ocAttr = transportEntry.get( "objectClass" ); 874 875 if ( ocAttr.contains( "ads-tcpTransport" ) ) 876 { 877 transport = new TcpTransport(); 878 } 879 else if ( ocAttr.contains( "ads-udpTransport" ) ) 880 { 881 transport = new UdpTransport(); 882 } 883 884 transport.setPort( getInt( "ads-systemPort", transportEntry ) ); 885 EntryAttribute addressAttr = transportEntry.get( "ads-transportAddress" ); 886 887 if ( addressAttr != null ) 888 { 889 transport.setAddress( addressAttr.getString() ); 890 } 891 else 892 { 893 transport.setAddress( "0.0.0.0" ); 894 } 895 896 EntryAttribute backlogAttr = transportEntry.get( "ads-transportBacklog" ); 897 898 if ( backlogAttr != null ) 899 { 900 transport.setBackLog( Integer.parseInt( backlogAttr.getString() ) ); 901 } 902 903 EntryAttribute sslAttr = transportEntry.get( "ads-transportEnableSSL" ); 904 905 if ( sslAttr != null ) 906 { 907 transport.setEnableSSL( Boolean.parseBoolean( sslAttr.getString() ) ); 908 } 909 910 EntryAttribute nbThreadsAttr = transportEntry.get( "ads-transportNbThreads" ); 911 912 if ( nbThreadsAttr != null ) 913 { 914 transport.setNbThreads( Integer.parseInt( nbThreadsAttr.getString() ) ); 915 } 916 917 return transport; 918 } 919 920 921 private ChangeLog getChangeLog( DN changelogDN ) throws Exception 922 { 923 long id = configPartition.getEntryId( changelogDN.getNormName() ); 924 Entry clEntry = configPartition.lookup( id ); 925 926 ChangeLog cl = new DefaultChangeLog(); 927 EntryAttribute clEnabledAttr = clEntry.get( "ads-changeLogEnabled" ); 928 929 if ( clEnabledAttr != null ) 930 { 931 cl.setEnabled( Boolean.parseBoolean( clEnabledAttr.getString() ) ); 932 } 933 934 EntryAttribute clExpAttr = clEntry.get( "ads-changeLogExposed" ); 935 936 if ( clExpAttr != null ) 937 { 938 cl.setExposed( Boolean.parseBoolean( clExpAttr.getString() ) ); 939 } 940 941 return cl; 942 } 943 944 945 private Journal getJournal( DN journalDN ) throws Exception 946 { 947 long id = configPartition.getEntryId( journalDN.getNormName() ); 948 Entry jlEntry = configPartition.lookup( id ); 949 950 Journal journal = new DefaultJournal(); 951 JournalStore store = new DefaultJournalStore(); 952 953 store.setFileName( getString( "ads-journalFileName", jlEntry ) ); 954 955 EntryAttribute jlWorkDirAttr = jlEntry.get( "ads-journalWorkingDir" ); 956 957 if ( jlWorkDirAttr != null ) 958 { 959 store.setWorkingDirectory( jlWorkDirAttr.getString() ); 960 } 961 962 EntryAttribute jlRotAttr = jlEntry.get( "ads-journalRotation" ); 963 964 if ( jlRotAttr != null ) 965 { 966 journal.setRotation( Integer.parseInt( jlRotAttr.getString() ) ); 967 } 968 969 EntryAttribute jlEnabledAttr = jlEntry.get( "ads-journalEnabled" ); 970 971 if ( jlEnabledAttr != null ) 972 { 973 journal.setEnabled( Boolean.parseBoolean( jlEnabledAttr.getString() ) ); 974 } 975 976 journal.setJournalStore( store ); 977 return journal; 978 } 979 980 981 private List<LdifEntry> getTestEntries( String entryFilePath ) throws Exception 982 { 983 List<LdifEntry> entries = new ArrayList<LdifEntry>(); 984 985 File file = new File( entryFilePath ); 986 987 if ( !file.exists() ) 988 { 989 LOG.warn( "LDIF test entry file path doesn't exist {}", entryFilePath ); 990 } 991 else 992 { 993 LOG.info( "parsing the LDIF file(s) present at the path {}", entryFilePath ); 994 loadEntries( file, entries ); 995 } 996 997 return entries; 998 } 999 1000 1001 private void loadEntries( File ldifFile, List<LdifEntry> entries ) throws Exception 1002 { 1003 if ( ldifFile.isDirectory() ) 1004 { 1005 File[] files = ldifFile.listFiles( ldifFilter ); 1006 1007 for ( File f : files ) 1008 { 1009 loadEntries( f, entries ); 1010 } 1011 } 1012 else 1013 { 1014 LdifReader reader = new LdifReader(); 1015 entries.addAll( reader.parseLdifFile( ldifFile.getAbsolutePath() ) ); 1016 reader.close(); 1017 } 1018 } 1019 1020 1021 private Set<WebApp> getWebApps( DN webAppsDN ) throws Exception 1022 { 1023 PresenceNode filter = new PresenceNode( "ads-httpWarFile" ); 1024 SearchControls controls = new SearchControls(); 1025 controls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 1026 IndexCursor<Long, ServerEntry, Long> cursor = se.cursor( webAppsDN, AliasDerefMode.NEVER_DEREF_ALIASES, filter, 1027 controls ); 1028 1029 Set<WebApp> webApps = new HashSet<WebApp>(); 1030 1031 while ( cursor.next() ) 1032 { 1033 ForwardIndexEntry<Long, ServerEntry, Long> forwardEntry = ( ForwardIndexEntry<Long, ServerEntry, Long> ) cursor 1034 .get(); 1035 ServerEntry webAppEntry = configPartition.lookup( forwardEntry.getId() ); 1036 1037 WebApp app = new WebApp(); 1038 app.setWarFile( getString( "ads-httpWarFile", webAppEntry ) ); 1039 1040 EntryAttribute ctxPathAttr = webAppEntry.get( "ads-httpAppCtxPath" ); 1041 1042 if ( ctxPathAttr != null ) 1043 { 1044 app.setContextPath( ctxPathAttr.getString() ); 1045 } 1046 1047 webApps.add( app ); 1048 } 1049 1050 return webApps; 1051 } 1052 1053 /** 1054 * internal class used for holding the Interceptor classname and order configuration 1055 */ 1056 private class InterceptorConfig implements Comparable<InterceptorConfig> 1057 { 1058 private String id; 1059 private String fqcn; 1060 private int order; 1061 1062 1063 public InterceptorConfig( String id, String fqcn, int order ) 1064 { 1065 if ( order < 1 ) 1066 { 1067 throw new IllegalArgumentException( I18n.err( I18n.ERR_507 ) ); 1068 } 1069 1070 this.id = id; 1071 this.fqcn = fqcn; 1072 this.order = order; 1073 } 1074 1075 1076 public int compareTo( InterceptorConfig o ) 1077 { 1078 if ( order > o.order ) 1079 { 1080 return 1; 1081 } 1082 else if ( order < o.order ) 1083 { 1084 return -1; 1085 } 1086 1087 return 0; 1088 } 1089 1090 1091 /** 1092 * @return the fqcn 1093 */ 1094 public String getFqcn() 1095 { 1096 return fqcn; 1097 } 1098 1099 } 1100 1101 1102 private String getString( String attrName, Entry entry ) throws Exception 1103 { 1104 return entry.get( attrName ).getString(); 1105 } 1106 1107 1108 private int getInt( String attrName, Entry entry ) throws Exception 1109 { 1110 return Integer.parseInt( entry.get( attrName ).getString() ); 1111 } 1112 1113 1114 private boolean isEnabled( Entry entry ) throws Exception 1115 { 1116 EntryAttribute enabledAttr = entry.get( "ads-enabled" ); 1117 if ( enabledAttr != null ) 1118 { 1119 return Boolean.parseBoolean( enabledAttr.getString() ); 1120 } 1121 else 1122 { 1123 return true; 1124 } 1125 } 1126 }