You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2004/06/24 09:06:37 UTC

svn commit: rev 21633 - in incubator/directory/eve/branches/start: . docs docs/design docs/issues src src/antlr src/conf src/docbook src/docbook/design src/docbook/design/operations src/images src/java src/java/org src/java/org/apache src/java/org/apache/eve src/java/org/apache/eve/backend src/java/org/apache/eve/backend/jdbm src/java/org/apache/eve/backend/jdbm/gui src/java/org/apache/eve/backend/jdbm/index src/java/org/apache/eve/backend/jdbm/search src/java/org/apache/eve/backend/jdbm/table src/java/org/apache/eve/backend/sql src/java/org/apache/eve/client src/java/org/apache/eve/decoder src/java/org/apache/eve/encoder src/java/org/apache/eve/event src/java/org/apache/eve/event/protocol src/java/org/apache/eve/input src/java/org/apache/eve/jndi src/java/org/apache/eve/listener src/java/org/apache/eve/output src/java/org/apache/eve/protocol src/java/org/apache/eve/protocol/event src/java/org/apache/eve/protocol/extended src/java/org/apache/eve/schema src/java/org/apache/eve/security src/java/org/apache/eve/security/auth src/java/org/apache/eve/seda src/ldif src/schema src/xdocs src/xdocs/images src/xdocs/images/design xdocs xdocs/design xdocs/design/operations xdocs/stylesheets

Author: akarasulu
Date: Thu Jun 24 00:06:35 2004
New Revision: 21633

Added:
   incubator/directory/eve/branches/start/
   incubator/directory/eve/branches/start/.classpath
   incubator/directory/eve/branches/start/.cvsignore
   incubator/directory/eve/branches/start/.project
   incubator/directory/eve/branches/start/ChangeLog.txt   (contents, props changed)
   incubator/directory/eve/branches/start/LICENSE.txt   (contents, props changed)
   incubator/directory/eve/branches/start/SearchProblems.txt   (contents, props changed)
   incubator/directory/eve/branches/start/build.xml   (contents, props changed)
   incubator/directory/eve/branches/start/default.properties
   incubator/directory/eve/branches/start/docs/
   incubator/directory/eve/branches/start/docs/design/
   incubator/directory/eve/branches/start/docs/issues/
   incubator/directory/eve/branches/start/docs/issues/normalization.txt   (contents, props changed)
   incubator/directory/eve/branches/start/maven.xml   (contents, props changed)
   incubator/directory/eve/branches/start/project.properties
   incubator/directory/eve/branches/start/project.xml   (contents, props changed)
   incubator/directory/eve/branches/start/sample.ant.properties
   incubator/directory/eve/branches/start/sample.build.properties
   incubator/directory/eve/branches/start/src/
   incubator/directory/eve/branches/start/src/antlr/
   incubator/directory/eve/branches/start/src/antlr/schema.g
   incubator/directory/eve/branches/start/src/conf/
   incubator/directory/eve/branches/start/src/conf/assembly.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/conf/config.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/conf/environment.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/
   incubator/directory/eve/branches/start/src/docbook/design/
   incubator/directory/eve/branches/start/src/docbook/design/authentication-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/backend-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/client-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/controls.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/decoder-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/encoder-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/event-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/input-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/jndi-provider-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/listener-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/module-implementation-template.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/nexus-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/operations/
   incubator/directory/eve/branches/start/src/docbook/design/operations/opertion-template.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/operations/search-operation.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/output-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/protocol-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/request-session-scopes.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/rootdse-design.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/schema-module.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/seda-implementation.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/server-architecture.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/docbook/design/triggers-and-procedures.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/
   incubator/directory/eve/branches/start/src/images/AddRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/AdminSchemaContext.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/BackendInterfaces.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/BindRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/CRUDLifecycle.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/CompareRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/DelRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ExtendedRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/InputEventHandlerHandleEvent.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/InputModuleRegister.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ListenerModuleRun.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ModifyDNRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ModifyRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ModuleDependencies.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/OutputEventHandlerHandleEvent.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/OutputModuleWrite.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ReqRespStageFlow.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/RequestEventHandlerHandleEvent.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/ResponseEventHandlerHandleEvent.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/SearchRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/images/UnBindRequestProcessorProcess.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/
   incubator/directory/eve/branches/start/src/java/org/
   incubator/directory/eve/branches/start/src/java/org/apache/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/AbstractModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/Kernel.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/Module.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AtomicBackend.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributeAdapter.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributesAdapter.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Backend.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendConfig.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Cursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EmptyCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EnumerationCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/IteratorCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/LdapEntry.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/NexusModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/NormalizerComponent.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/ReadOnlyException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/RootDSE.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/SingletonCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/UnifiedBackend.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/backendhowto.html
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/contract.html
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/dnnormalization.html
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/Database.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/EntryCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/IndexNotFoundException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmDatabase.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/LdapEntryImpl.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/ASTNode.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AboutDialog.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AnnotatedFilterTreeDialog.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/BackendFrame.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/EntryNode.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/FilterDialog.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/IndexDialog.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmBackendViewer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmTableModel.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/MultiMapModel.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/SearchResultDialog.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/ldapd.gif   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/BigIntegerComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/Index.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexRecord.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/JdbmIndex.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/StringComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Assertion.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DefaultOptimizer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DisjunctionCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Optimizer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/PrefetchCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/SearchEngine.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/DupsCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/JdbmTable.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/KeyOnlyComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/MasterTable.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/NoDupsCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/Table.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TableComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleComparator.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleIteratorCursor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleRenderer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/package.html
   incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/sql/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientKey.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManagerSlave.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientSession.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/KeyExpiryException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/LdapClientSession.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ServerConfig.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/Decoder.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/Encoder.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AbstractEventHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEventSource.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EventHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AbandonEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AddEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/BindEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/CompareEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/DelEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ExtendedEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyDnEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolAdapter.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/SearchEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/UnbindEvent.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/input/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/BindingEnumeration.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ContextHelper.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/DirContextHelper.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProvider.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProviderModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/NameClassPairEnumeration.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/SearchResultEnumeration.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ServerContextFactory.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedContext.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedDirContext.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedLdapContext.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ServerListener.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/output/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AbandonHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AddHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/BindHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/CompareHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/DeleteHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ExtendedHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/HandlerTypeEnum.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDNRequestProcessor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDnHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/NoReplyHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolEngine.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/RequestHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchRequestProcessor.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SingleReplyHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Stats.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/UnbindHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Utils.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/event/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/extended/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/extended/PayloadHandler.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/AttributeSpec.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Normalizer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ObjectClassSpec.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ParserSyntaxChecker.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexNormalizer.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexSyntaxChecker.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Schema.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaImpl.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SyntaxChecker.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/LdapPrincipal.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationException.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationManager.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationModule.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/
   incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/AbstractStage.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/EnqueuePredicate.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/Stage.java   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/
   incubator/directory/eve/branches/start/src/ldif/addAll.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/addRoot.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/addTestUser.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/example.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/ori_example.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/ldif/smallest_example.ldif   (contents, props changed)
   incubator/directory/eve/branches/start/src/schema/
   incubator/directory/eve/branches/start/src/schema/corba.schema
   incubator/directory/eve/branches/start/src/schema/core.schema
   incubator/directory/eve/branches/start/src/schema/core.xml   (contents, props changed)
   incubator/directory/eve/branches/start/src/schema/cosine.schema
   incubator/directory/eve/branches/start/src/schema/inetorgperson.schema
   incubator/directory/eve/branches/start/src/schema/java.schema
   incubator/directory/eve/branches/start/src/schema/krb5-kdc.schema
   incubator/directory/eve/branches/start/src/schema/misc.schema
   incubator/directory/eve/branches/start/src/schema/nis.schema
   incubator/directory/eve/branches/start/src/schema/openldap.schema
   incubator/directory/eve/branches/start/src/schema/our.schema
   incubator/directory/eve/branches/start/src/schema/vendor.schema
   incubator/directory/eve/branches/start/src/xdocs/
   incubator/directory/eve/branches/start/src/xdocs/images/
   incubator/directory/eve/branches/start/src/xdocs/images/design/
   incubator/directory/eve/branches/start/todo.txt   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/
   incubator/directory/eve/branches/start/xdocs/design/
   incubator/directory/eve/branches/start/xdocs/design/operations/
   incubator/directory/eve/branches/start/xdocs/design/operations/index.xml   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/design/operations/navigation.xml   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/devprocess.xml   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/index.xml   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/navigation.xml   (contents, props changed)
   incubator/directory/eve/branches/start/xdocs/stylesheets/
   incubator/directory/eve/branches/start/xdocs/stylesheets/tigris.css
   incubator/directory/eve/branches/start/xdocs/temp.xml   (contents, props changed)
Log:
Initial Eve State on SVN Import - A MAINTENANCE BRANCH ONLY FOR BUG FIXES

Added: incubator/directory/eve/branches/start/.classpath
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/.classpath	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<classpath>
+  <classpathentry kind="src" path="src/java">
+  </classpathentry>
+  <classpathentry kind="var" rootpath="JRE_SRCROOT" path="JRE_LIB" sourcepath="JRE_SRC">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/commons-logging/jars/commons-logging-1.0.2.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/oro/jars/oro-2.0.7.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/cornerstone-threads/jars/cornerstone-threads-impl-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/cornerstone-threads/jars/cornerstone-threads-api-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/excalibur-thread/jars/excalibur-thread-1.1.1.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/avalon-phoenix/jars/avalon-phoenix-client-4.0.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/ldapd-common/jars/ldapd-common-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/ldapd-snacc-provider/jars/ldapd-snacc-provider-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/commons-collections/jars/commons-collections-2.1.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/regexp/jars/regexp-1.2.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/antlr/jars/antlr-2.7.2.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/avalon-framework/jars/avalon-framework-api-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="var" path="MAVEN_REPO/avalon-framework/jars/avalon-framework-impl-SNAPSHOT.jar">
+  </classpathentry>
+  <classpathentry kind="output" path="target/classes">
+  </classpathentry>
+</classpath>
\ No newline at end of file

Added: incubator/directory/eve/branches/start/.cvsignore
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/.cvsignore	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,22 @@
+*.twr
+*.tpr
+*.tws
+*.log
+*.db
+.nbattrs
+antlr*
+test*
+target
+dist
+build
+diagrams
+testdb*
+classes
+together
+build.properties
+together/newton/diagrams
+*javadocs
+SchemaParser.java
+SchemaSyntaxLexer.java
+SchemaTokenTypes.java
+SchemaTokenTypes.txt

Added: incubator/directory/eve/branches/start/.project
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/.project	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<projectDescription>
+  <name>ldapd-server</name>
+  <comment>Common LDAP packages used for protocol compliant parsing of distinguished names, LDIFs, filters, and urls. Also contains the Common Message API which enables a plugable interface for ASN.1 BER Message providers.</comment>
+  <projects>
+  </projects>
+  <buildSpec>
+    <buildCommand>
+      <name>org.eclipse.jdt.core.javabuilder</name>
+      <arguments>
+      </arguments>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>
\ No newline at end of file

Added: incubator/directory/eve/branches/start/ChangeLog.txt
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/ChangeLog.txt	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,17 @@
+Release 0.71a
+=============
+
+* Refactored ClientKeys to throw KeyExpiryExceptions.
+* Modified OutputModule to handle expirations and it now buffers client writes.
+* Enabled use of IO lock objects in InputModule and DecoderModule.
+* InputModule's InputStreamMonitor now politely exits when the ClientKey is
+  expired rather than exiting due to an IOException on the InputStream.
+* Cleaned up the ClientManager interface and its ClientModule implementation
+  to enable named and anonymous sessions.
+* ClientModule now dependent on Nexus which has become a ClientManagerSlave
+  along with all backends.
+* ProtocolEngine now uses ClientManager interface methods to assiciate worker
+  threads with clients when they process requests on behalf of the client.
+* Added ability to transparently inject or alter operational attributes within
+  the nexus module.
+

Added: incubator/directory/eve/branches/start/LICENSE.txt
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/LICENSE.txt	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,204 @@
+/*
+ *                                 Apache License
+ *                           Version 2.0, January 2004
+ *                        http://www.apache.org/licenses/
+ *
+ *   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ *   1. Definitions.
+ *
+ *      "License" shall mean the terms and conditions for use, reproduction,
+ *      and distribution as defined by Sections 1 through 9 of this document.
+ *
+ *      "Licensor" shall mean the copyright owner or entity authorized by
+ *      the copyright owner that is granting the License.
+ *
+ *      "Legal Entity" shall mean the union of the acting entity and all
+ *      other entities that control, are controlled by, or are under common
+ *      control with that entity. For the purposes of this definition,
+ *      "control" means (i) the power, direct or indirect, to cause the
+ *      direction or management of such entity, whether by contract or
+ *      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ *      outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ *      "You" (or "Your") shall mean an individual or Legal Entity
+ *      exercising permissions granted by this License.
+ *
+ *      "Source" form shall mean the preferred form for making modifications,
+ *      including but not limited to software source code, documentation
+ *      source, and configuration files.
+ *
+ *      "Object" form shall mean any form resulting from mechanical
+ *      transformation or translation of a Source form, including but
+ *      not limited to compiled object code, generated documentation,
+ *      and conversions to other media types.
+ *
+ *      "Work" shall mean the work of authorship, whether in Source or
+ *      Object form, made available under the License, as indicated by a
+ *      copyright notice that is included in or attached to the work
+ *      (an example is provided in the Appendix below).
+ *
+ *      "Derivative Works" shall mean any work, whether in Source or Object
+ *      form, that is based on (or derived from) the Work and for which the
+ *      editorial revisions, annotations, elaborations, or other modifications
+ *      represent, as a whole, an original work of authorship. For the purposes
+ *      of this License, Derivative Works shall not include works that remain
+ *      separable from, or merely link (or bind by name) to the interfaces of,
+ *      the Work and Derivative Works thereof.
+ *
+ *      "Contribution" shall mean any work of authorship, including
+ *      the original version of the Work and any modifications or additions
+ *      to that Work or Derivative Works thereof, that is intentionally
+ *      submitted to Licensor for inclusion in the Work by the copyright owner
+ *      or by an individual or Legal Entity authorized to submit on behalf of
+ *      the copyright owner. For the purposes of this definition, "submitted"
+ *      means any form of electronic, verbal, or written communication sent
+ *      to the Licensor or its representatives, including but not limited to
+ *      communication on electronic mailing lists, source code control systems,
+ *      and issue tracking systems that are managed by, or on behalf of, the
+ *      Licensor for the purpose of discussing and improving the Work, but
+ *      excluding communication that is conspicuously marked or otherwise
+ *      designated in writing by the copyright owner as "Not a Contribution."
+ *
+ *      "Contributor" shall mean Licensor and any individual or Legal Entity
+ *      on behalf of whom a Contribution has been received by Licensor and
+ *      subsequently incorporated within the Work.
+ *
+ *   2. Grant of Copyright License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      copyright license to reproduce, prepare Derivative Works of,
+ *      publicly display, publicly perform, sublicense, and distribute the
+ *      Work and such Derivative Works in Source or Object form.
+ *
+ *   3. Grant of Patent License. Subject to the terms and conditions of
+ *      this License, each Contributor hereby grants to You a perpetual,
+ *      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ *      (except as stated in this section) patent license to make, have made,
+ *      use, offer to sell, sell, import, and otherwise transfer the Work,
+ *      where such license applies only to those patent claims licensable
+ *      by such Contributor that are necessarily infringed by their
+ *      Contribution(s) alone or by combination of their Contribution(s)
+ *      with the Work to which such Contribution(s) was submitted. If You
+ *      institute patent litigation against any entity (including a
+ *      cross-claim or counterclaim in a lawsuit) alleging that the Work
+ *      or a Contribution incorporated within the Work constitutes direct
+ *      or contributory patent infringement, then any patent licenses
+ *      granted to You under this License for that Work shall terminate
+ *      as of the date such litigation is filed.
+ *
+ *   4. Redistribution. You may reproduce and distribute copies of the
+ *      Work or Derivative Works thereof in any medium, with or without
+ *      modifications, and in Source or Object form, provided that You
+ *      meet the following conditions:
+ *
+ *      (a) You must give any other recipients of the Work or
+ *          Derivative Works a copy of this License; and
+ *
+ *      (b) You must cause any modified files to carry prominent notices
+ *          stating that You changed the files; and
+ *
+ *      (c) You must retain, in the Source form of any Derivative Works
+ *          that You distribute, all copyright, patent, trademark, and
+ *          attribution notices from the Source form of the Work,
+ *          excluding those notices that do not pertain to any part of
+ *          the Derivative Works; and
+ *
+ *      (d) If the Work includes a "NOTICE" text file as part of its
+ *          distribution, then any Derivative Works that You distribute must
+ *          include a readable copy of the attribution notices contained
+ *          within such NOTICE file, excluding those notices that do not
+ *          pertain to any part of the Derivative Works, in at least one
+ *          of the following places: within a NOTICE text file distributed
+ *          as part of the Derivative Works; within the Source form or
+ *          documentation, if provided along with the Derivative Works; or,
+ *          within a display generated by the Derivative Works, if and
+ *          wherever such third-party notices normally appear. The contents
+ *          of the NOTICE file are for informational purposes only and
+ *          do not modify the License. You may add Your own attribution
+ *          notices within Derivative Works that You distribute, alongside
+ *          or as an addendum to the NOTICE text from the Work, provided
+ *          that such additional attribution notices cannot be construed
+ *          as modifying the License.
+ *
+ *      You may add Your own copyright statement to Your modifications and
+ *      may provide additional or different license terms and conditions
+ *      for use, reproduction, or distribution of Your modifications, or
+ *      for any such Derivative Works as a whole, provided Your use,
+ *      reproduction, and distribution of the Work otherwise complies with
+ *      the conditions stated in this License.
+ *
+ *   5. Submission of Contributions. Unless You explicitly state otherwise,
+ *      any Contribution intentionally submitted for inclusion in the Work
+ *      by You to the Licensor shall be under the terms and conditions of
+ *      this License, without any additional terms or conditions.
+ *      Notwithstanding the above, nothing herein shall supersede or modify
+ *      the terms of any separate license agreement you may have executed
+ *      with Licensor regarding such Contributions.
+ *
+ *   6. Trademarks. This License does not grant permission to use the trade
+ *      names, trademarks, service marks, or product names of the Licensor,
+ *      except as required for reasonable and customary use in describing the
+ *      origin of the Work and reproducing the content of the NOTICE file.
+ *
+ *   7. Disclaimer of Warranty. Unless required by applicable law or
+ *      agreed to in writing, Licensor provides the Work (and each
+ *      Contributor provides its Contributions) on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *      implied, including, without limitation, any warranties or conditions
+ *      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ *      PARTICULAR PURPOSE. You are solely responsible for determining the
+ *      appropriateness of using or redistributing the Work and assume any
+ *      risks associated with Your exercise of permissions under this License.
+ *
+ *   8. Limitation of Liability. In no event and under no legal theory,
+ *      whether in tort (including negligence), contract, or otherwise,
+ *      unless required by applicable law (such as deliberate and grossly
+ *      negligent acts) or agreed to in writing, shall any Contributor be
+ *      liable to You for damages, including any direct, indirect, special,
+ *      incidental, or consequential damages of any character arising as a
+ *      result of this License or out of the use or inability to use the
+ *      Work (including but not limited to damages for loss of goodwill,
+ *      work stoppage, computer failure or malfunction, or any and all
+ *      other commercial damages or losses), even if such Contributor
+ *      has been advised of the possibility of such damages.
+ *
+ *   9. Accepting Warranty or Additional Liability. While redistributing
+ *      the Work or Derivative Works thereof, You may choose to offer,
+ *      and charge a fee for, acceptance of support, warranty, indemnity,
+ *      or other liability obligations and/or rights consistent with this
+ *      License. However, in accepting such obligations, You may act only
+ *      on Your own behalf and on Your sole responsibility, not on behalf
+ *      of any other Contributor, and only if You agree to indemnify,
+ *      defend, and hold each Contributor harmless for any liability
+ *      incurred by, or claims asserted against, such Contributor by reason
+ *      of your accepting any such warranty or additional liability.
+ *
+ *   END OF TERMS AND CONDITIONS
+ *
+ *   APPENDIX: How to apply the Apache License to your work.
+ *
+ *      To apply the Apache License to your work, attach the following
+ *      boilerplate notice, with the fields enclosed by brackets "[]"
+ *      replaced with your own identifying information. (Don't include
+ *      the brackets!)  The text should be enclosed in the appropriate
+ *      comment syntax for the file format. We also recommend that a
+ *      file or class name and description of purpose be included on the
+ *      same "printed page" as the copyright notice for easier
+ *      identification within third-party archives.
+ *
+ *   Copyright [yyyy] [name of copyright owner]
+ *
+ *   Licensed 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.
+ *
+ */

Added: incubator/directory/eve/branches/start/SearchProblems.txt
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/SearchProblems.txt	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,59 @@
+            Problems With The Search Operation
+--------------------------------------------------------------
+
+* The following search parameters are not taken into account:
+
+    - timeLimit
+    - sizeLimit
+    - typesOnly
+    - derefAliases
+
+* Pruning of undefined filter assertions does not occur.
+  This must happen to facilitate the behavoir defined for
+  searches with invalid filter expressions in accordance
+  with RFC 2251.
+
+* Alias dereferencing obviously from the list above is not 
+  supported at the present moment.
+
+* Referals are not supported at all by the search processor
+  at the present moment.
+
+* The search entry responses do not add binary flags in the 
+  attribute description for binary attributes.
+
+* Note that all requests except for abandon and unbind (which
+  do not return responses) can return a referal to find the 
+  target entry.  Only the search requests manage the resolution
+  of referals and aliases.
+
+* Extensible matching is not enabled.
+
+* Undefined filter assertion pruning is not performed.
+
+* The attribute list to return is not supported and all 
+  including operational attributes are returned.  We need to
+  return all attributes (but not operational attributes) if 
+  the attribute list is empty or has a "*" wild card (which 
+  returns operational attributes as well.
+
+* Need to recognize the special reserved "1.1" attribute OID 
+  in the attribute list to connotate the return of none of the 
+  attributes in the entry.
+
+
+
+                   Other Protocol Violations
+--------------------------------------------------------------
+
+* Notice of Disconnect not implemented.
+
+* Referal error not returned when base Dn of operation is a 
+  referal.
+
+* LDAP URLs are not supported with the '%' escape syntax of 
+  RFC 1738.
+
+* Control criticality is not checked on unrecognized controls.
+
+

Added: incubator/directory/eve/branches/start/build.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/build.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,759 @@
+<?xml version="1.0"?>
+<project name="eve" default="sars" basedir=".">
+
+	<!-- ============================================================
+                           PROPERTY SETUP
+  ============================================================= -->
+
+	<!-- load properties files -->
+	<property file="${user.home}/build.properties"/>
+	<property file="${user.home}/.ant.properties"/>
+	<property file="${basedir}/ant.properties"/>
+	<property file="${basedir}/../ant.properties"/>
+	<property file="${basedir}/default.properties"/>
+	<property file="${basedir}/../default.properties"/>
+	<property file="${basedir}/../cocoon.properties"/>
+
+	<!-- Set the properties for intermediate directory -->
+	<property name="build.dir" value="build"/>
+	<property name="build.lib" value="${build.dir}/lib"/>
+	<property name="build.xdoclet" value="${build.dir}/xdoclet"/>
+	<property name="build.src" value="${build.dir}/src"/>
+	<property name="build.classes" value="${build.dir}/classes"/>
+	<property name="build.javadocs" value="${build.dir}/javadocs"/>
+	<property name="build.docs" value="${build.dir}/docs"/>
+	<property name="build.context" value="${build.dir}/documentation"/>
+	<property name="build.xdocs" value="${build.context}/content/xdocs"/>
+
+	<!-- Set the properties for source directories -->
+	<property name="src.dir" value="src"/>
+	<property name="java.dir" value="${src.dir}/java"/>
+	<property name="manifest.dir" value="${src.dir}/manifest"/>
+	<property name="conf.dir" value="${src.dir}/conf"/>
+	<property name="xdocs.dir" value="${src.dir}/xdocs"/>
+	<property name="dist.base" value="distributions"/>
+  <property name="remote.repo" value="http://cvs.apache.org/repository"/>
+
+  <property environment="env"/>
+
+  <!-- ============================================================
+                   DEPENDENCY JARS PROPERTY SETUP
+  ============================================================= -->
+
+  <property
+    name="ldap-common.jar"
+    value="ldap-common-SNAPSHOT.jar"/>
+
+	<property
+    name="commons-collections.jar"
+    value="commons-collections-2.1.jar"/>
+
+	<property
+    name="commons-lang.jar"
+    value="commons-lang-2.0.jar"/>
+
+	<property
+    name="snacc.jar"
+    value="snacc-2.3.jar"/>
+
+	<property
+    name="antlr.jar"
+    value="antlr-2.7.2.jar"/>
+
+	<property
+    name="avalon-framework-api.jar"
+    value="avalon-framework-api-4.1.5.jar"/>
+
+  <property
+    name="avalon-framework-impl.jar"
+    value="avalon-framework-impl-4.1.5.jar"/>
+
+  <property
+    name="regexp.jar"
+    value="regexp-1.2.jar"/>
+
+  <property
+    name="ldap-snacc-provider.jar"
+    value="ldap-snacc-provider-SNAPSHOT.jar"/>
+
+  <property
+    name="oro.jar"
+    value="oro-2.0.7.jar"/>
+
+  <property
+    name="cornerstone-threads-api.jar"
+    value="cornerstone-threads-api-2.0.jar" />
+
+  <property
+    name="cornerstone-threads-impl.jar"
+    value="cornerstone-threads-impl-2.0.jar" />
+
+  <property
+    name="excalibur-thread.jar"
+    value="excalibur-thread-1.1.1.jar"/>
+
+  <property
+    name="jdbm.jar"
+    value="jdbm-0.12.jar"/>
+
+  <property
+    name="logkit.jar"
+    value="logkit-1.2.jar"/>
+
+  <!-- ============================================================
+                      TOOLS JARS PROPERTY SETUP
+  ============================================================= -->
+
+  <property
+    name="xdoclet.jar"
+    value="xdoclet-20020825.jar"/>
+
+  <property
+    name="xjavadoc.jar"
+    value="xjavadoc-20020825.jar"/>
+
+  <property
+    name="phoenix-client.jar"
+    value="avalon-phoenix-client-4.0.4.jar"/>
+
+  <property
+    name="commons-logging.jar"
+    value="commons-logging-1.0.3.jar"/>
+
+  <property
+    name="log4j.jar"
+    value="log4j-1.2.7.jar"/>
+
+  <property
+    name="velocity.jar"
+    value="velocity-1.3.jar"/>
+
+  <property
+    name="jdom.jar"
+    value="jdom-b7.jar"/>
+
+  <!-- ============================================================
+                           CLASSPATH SETUP
+  ============================================================= -->
+
+	<!-- Set some class paths -->
+	<path id="project.class.path">
+		<pathelement path="${java.class.path}"/>
+		<pathelement path="${build.classes}"/>
+		<pathelement path="${build.lib}/${ldap-common.jar}"/>
+		<pathelement path="${build.lib}/${commons-lang.jar}"/>
+		<pathelement path="${build.lib}/${snacc.jar}"/>
+		<pathelement path="${build.lib}/${antlr.jar}"/>
+		<pathelement path="${build.lib}/${avalon-framework-api.jar}"/>
+		<pathelement path="${build.lib}/${avalon-framework-impl.jar}"/>
+		<pathelement path="${build.lib}/${commons-collections.jar}"/>
+		<pathelement path="${build.lib}/${regexp.jar}"/>
+		<pathelement path="${build.lib}/${oro.jar}"/>
+		<pathelement path="${build.lib}/${cornerstone-threads-api.jar}"/>
+		<pathelement path="${build.lib}/${cornerstone-threads-impl.jar}"/>
+		<pathelement path="${build.lib}/${phoenix-client.jar}"/>
+    <pathelement path="${build.lib}/${excalibur-thread.jar}"/>
+    <pathelement path="${build.lib}/${jdbm.jar}"/>
+    <pathelement path="${build.lib}/${logkit.jar}"/>
+	</path>
+
+	<path id="tools.class.path">
+		<path refid="project.class.path"/>
+    <pathelement location="${build.lib}/${log4j.jar}"/>
+    <pathelement location="${build.lib}/${commons-logging.jar}"/>
+    <pathelement location="${build.lib}/${xdoclet.jar}"/>
+    <pathelement location="${build.lib}/${xjavadoc.jar}"/>
+    <pathelement location="${build.lib}/${phoenix-client.jar}"/>
+    <pathelement location="${build.lib}/${velocity.jar}"/>
+    <pathelement location="${build.lib}/${jdom.jar}"/>
+	</path>
+
+
+  <target name="get-deps">
+    <mkdir dir="${build.lib}"/>
+
+    <!-- ======================================================================
+                              GET TOOL DEPENDENCY JARS
+    ======================================================================= -->
+
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/log4j/jars/${log4j.jar}"
+      dest="${build.lib}/${log4j.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/commons-logging/jars/${commons-logging.jar}"
+      dest="${build.lib}/${commons-logging.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/xdoclet/jars/${xdoclet.jar}"
+      dest="${build.lib}/${xdoclet.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/xjavadoc/jars/${xjavadoc.jar}"
+      dest="${build.lib}/${xjavadoc.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/avalon-phoenix/jars/${phoenix-client.jar}"
+      dest="${build.lib}/${phoenix-client.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/velocity/jars/${velocity.jar}"
+      dest="${build.lib}/${velocity.jar}"
+      verbose="true"
+      />
+    <get
+      usetimestamp="true"
+      src="${remote.repo}/jdom/jars/${jdom.jar}"
+      dest="${build.lib}/${jdom.jar}"
+      verbose="true"
+      />
+
+    <!-- ======================================================================
+                                GET DEPENDENCY JARS
+    ======================================================================= -->
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/incubator-directory/jars/${ldap-common.jar}"
+      dest="${build.lib}/${ldap-common.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/incubator-directory/jars/${ldap-snacc-provider.jar}"
+      dest="${build.lib}/${ldap-snacc-provider.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/commons-lang/jars/${commons-lang.jar}"
+      dest="${build.lib}/${commons-lang.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="http://ldapd.sourceforge.net/maven/repository/snacc4j/jars/${snacc.jar}"
+      dest="${build.lib}/${snacc.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/antlr/jars/${antlr.jar}"
+      dest="${build.lib}/${antlr.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/avalon-framework/jars/${avalon-framework-api.jar}"
+      dest="${build.lib}/${avalon-framework-api.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/avalon-framework/jars/${avalon-framework-impl.jar}"
+      dest="${build.lib}/${avalon-framework-impl.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/commons-collections/jars/${commons-collections.jar}"
+      dest="${build.lib}/${commons-collections.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/regexp/jars/${regexp.jar}"
+      dest="${build.lib}/${regexp.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/oro/jars/${oro.jar}"
+      dest="${build.lib}/${oro.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/cornerstone-threads/jars/${cornerstone-threads-api.jar}"
+      dest="${build.lib}/${cornerstone-threads-api.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/cornerstone-threads/jars/${cornerstone-threads-impl.jar}"
+      dest="${build.lib}/${cornerstone-threads-impl.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/excalibur-thread/jars/${excalibur-thread.jar}"
+      dest="${build.lib}/${excalibur-thread.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/jdbm/jars/${jdbm.jar}"
+      dest="${build.lib}/${jdbm.jar}"
+      />
+
+    <get verbose="true" usetimestamp="true"
+      src="${remote.repo}/logkit/jars/${logkit.jar}"
+      dest="${build.lib}/${logkit.jar}"
+      />
+  </target>
+
+	<!-- ======================================================
+
+
+			       T A R G E T S
+
+
+	======================================================= -->
+
+
+	<!-- ======================================================
+			    C O M P I L A T I O N
+	======================================================= -->
+
+	
+	<target name="grammars" depends="get-deps">
+		<antlr target="src/antlr/schema.g" 
+			   outputdirectory="src/java/org/apache/eve/schema">
+			<classpath refid="tools.class.path"/>
+		</antlr>
+	</target>
+
+
+	<target name="compile" depends="grammars">
+		<mkdir dir="${build.classes}"/>
+
+		<javac srcdir="${java.dir}"
+      destdir="${build.classes}"
+      debug="${build.debug}"
+      optimize="${build.optimize}"
+      deprecation="${build.deprecation}">
+			<classpath refid="project.class.path"/>
+		</javac>
+
+		<copy todir="${build.classes}">
+			<fileset dir="${java.dir}">
+				<exclude name="**/test/**"/>
+				<exclude name="**/*.java"/>
+			</fileset>
+		</copy>
+	</target>
+
+
+	<!-- ======================================================
+	X I N F O   A N D   M A N I F E S T   G E N E R A T I O N 
+	======================================================= -->
+	
+	<target name="test-xdoclet">
+		<available classname="xdoclet.XDocletMain"
+      classpathref="tools.class.path"
+      property="xdoclet.present"/>
+	</target>
+	
+	<target name="phoenix-xdoclet" depends="compile" ><!--if="xdoclet.present"-->
+		<mkdir dir="${build.xdoclet}"/>
+		<taskdef
+      name="phoenix-blocks"
+      classname="org.apache.avalon.phoenix.tools.xdoclet.PhoenixXDoclet"
+      classpathref="tools.class.path"/>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/event/protocol/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/jndi/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/input/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/output/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/encoder/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/security/auth/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/protocol/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/decoder/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/client/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/schema/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/listener/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+		<phoenix-blocks destdir="${build.xdoclet}">
+			<fileset dir="${java.dir}">
+				<include name="org/apache/eve/backend/*.java"/>
+			</fileset>
+			<blockinfo/>
+			<mxinfo/>
+		</phoenix-blocks>
+
+    <phoenix-blocks destdir="${build.xdoclet}">
+      <fileset dir="${java.dir}">
+        <include name="org/apache/eve/backend/jdbm/*.java"/>
+      </fileset>
+      <blockinfo/>
+      <mxinfo/>
+    </phoenix-blocks>
+	</target>
+
+
+	<!-- Make .xinfo and manifest automatically for blocks -->
+	<target name="no-phoenix-xdoclet" depends="compile" unless="xdoclet.present">
+		<mkdir dir="${build.xdoclet}"/>
+		<unzip src="${src.dir}/generated-by-xdoclet.zip" dest="${build.xdoclet}"/>
+	</target>
+
+	<!-- ======================================================
+					        P R O J E C T    J A R S
+	======================================================= -->
+
+	<target name="jars" depends="phoenix-xdoclet">
+    <!--depends="test-xdoclet, phoenix-xdoclet, no-phoenix-xdoclet"-->
+		<mkdir dir="${build.lib}"/>
+
+		<!-- Just jars the individual block packages not the required set of classes 
+			 the core classes need to be jared into a separate core.jar.
+		-->
+
+		<jar jarfile="${build.lib}/core.jar" basedir="${build.classes}">
+			<!-- Include entire package -->
+			<include name="org/apache/eve/**"/>
+
+			<!-- Exclude the blocks jared below -->
+			<exclude name="org/apache/eve/input/*"/>
+			<exclude name="org/apache/eve/output/*"/>
+      <exclude name="org/apache/eve/encoder/*"/>
+			<exclude name="org/apache/eve/event/protocol/*"/>
+			<exclude name="org/apache/eve/security/auth/*"/>
+			<exclude name="org/apache/eve/protocol/*"/>
+			<exclude name="org/apache/eve/decoder/*"/>
+			<exclude name="org/apache/eve/client/*"/>
+			<exclude name="org/apache/eve/schema/*"/>
+			<exclude name="org/apache/eve/listener/*"/>
+			<exclude name="org/apache/eve/backend/*"/>
+		</jar>
+
+		<jar jarfile="${build.lib}/event.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/event/protocol/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/event/protocol/*.xinfo"/>
+				<include name="org/apache/eve/event/protocol/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/jndi.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/jndi/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/jndi/*.xinfo"/>
+				<include name="org/apache/eve/jndi/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/input.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/input/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/input/*.xinfo"/>
+				<include name="org/apache/eve/input/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/output.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/output/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/output/*.xinfo"/>
+				<include name="org/apache/eve/output/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/encoder.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/encoder/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/encoder/*.xinfo"/>
+				<include name="org/apache/eve/encoder/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/authman.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/security/auth/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/security/auth/*.xinfo"/>
+				<include name="org/apache/eve/security/auth/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/protocol.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/protocol/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/protocol/*.xinfo"/>
+				<include name="org/apache/eve/protocol/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/decoder.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/decoder/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/decoder/*.xinfo"/>
+				<include name="org/apache/eve/decoder/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/client.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/client/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/client/*.xinfo"/>
+				<include name="org/apache/eve/client/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/listener.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/listener/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/listener/*.xinfo"/>
+				<include name="org/apache/eve/listener/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/schema.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/schema/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/schema/*.xinfo"/>
+				<include name="org/apache/eve/schema/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+		<jar jarfile="${build.lib}/backend.jar" basedir="${build.classes}">
+			<include name="org/apache/eve/backend/*"/>
+			<fileset dir="${build.xdoclet}">
+				<include name="org/apache/eve/backend/*.xinfo"/>
+				<include name="org/apache/eve/backend/*.mxinfo"/>
+			</fileset>
+		</jar>
+
+    <jar jarfile="${build.lib}/backjdbm.jar" basedir="${build.classes}">
+      <include name="org/apache/eve/backend/jdbm/**"/>
+      <fileset dir="${build.xdoclet}">
+        <include name="org/apache/eve/backend/jdbm/*.xinfo"/>
+        <include name="org/apache/eve/backend/jdbm/*.mxinfo"/>
+      </fileset>
+    </jar>
+	</target>
+
+
+	<!-- ======================================================
+					        C O R E    T A R G E T S
+	======================================================= -->
+
+	<target name="sars" depends="jars">
+    <taskdef name="sar" classname="org.apache.avalon.phoenix.tools.tasks.Sar">
+      <classpath refid="tools.class.path"/>
+    </taskdef>
+
+    <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask">
+      <classpath refid="tools.class.path"/>
+    </taskdef>
+
+    <sar sarfile="${build.lib}/eve.sar"
+			config="${conf.dir}/config.xml" 
+			environment="${conf.dir}/environment.xml" 
+			assembly="${conf.dir}/assembly.xml">
+
+			<lib dir="src">
+				<include name="schema/**.schema"/>
+			</lib>
+
+			<lib dir="${build.lib}/">
+				<include name="${antlr.jar}"/>
+        <include name="authman.jar"/>
+        <include name="${avalon-framework-api.jar}"/>
+        <include name="${avalon-framework-impl.jar}"/>
+        <include name="${phoenix-client.jar}"/>
+        <include name="backend.jar"/>
+        <include name="backjdbm.jar"/>
+        <include name="client.jar"/>
+        <include name="${commons-collections.jar}"/>
+        <include name="${commons-lang.jar}"/>
+        <include name="${commons-logging.jar}"/>
+        <include name="core.jar"/>
+        <include name="${cornerstone-threads-api.jar}"/>
+        <include name="${cornerstone-threads-impl.jar}"/>
+        <include name="decoder.jar"/>
+        <include name="encoder.jar"/>
+				<include name="event.jar"/>
+        <include name="${excalibur-thread.jar}"/>
+        <include name="input.jar"/>
+        <include name="${jdbm.jar}"/>
+				<include name="jndi.jar"/>
+        <include name="${ldap-common.jar}"/>
+        <include name="${ldap-snacc-provider.jar}"/>
+				<include name="listener.jar"/>
+        <include name="${logkit.jar}"/>
+				<include name="${oro.jar}"/>
+        <include name="output.jar"/>
+        <include name="protocol.jar"/>
+        <include name="${regexp.jar}"/>
+				<include name="schema.jar"/>
+				<include name="${snacc.jar}"/>
+			</lib>
+		</sar>
+
+		<mkdir dir="dist"/>
+		<copy todir="dist">
+			<fileset dir="${build.lib}">
+				<include name="*.sar"/>
+			</fileset>
+		</copy>
+
+		<echo message="done with sars"/>
+	</target>
+
+
+	<!-- ======================================================
+				  I N S T A L L     D E P L O Y
+	======================================================= -->
+
+  <target name="findInstallDir" unless="${install.dir}">
+    <property name="phoenix.home" value="${env.PHOENIX_HOME}"/>
+    <condition property="install.dir" value="${env.PHOENIX_HOME}/apps">
+      <not>
+        <contains string="${phoenix.home}" substring="env.PHOENIX_HOME"/>
+      </not>
+    </condition>
+  </target>
+
+  <target name="doPhoenixInstall"
+    unless="install.dir" depends="findInstallDir" >
+
+    <echo message="PHOENIX_HOME NOT SET!"/>
+    <echo message="CANNOT FIND PHOENIX INSTALLATION!"/>
+    <input
+      message="Would you like to download and install Phoenix into ./dist?"
+      validargs="yes,no"
+      addproperty="install.phoenix"/>
+  </target>
+
+  <target name="installPhoenix" depends="doPhoenixInstall" if="install.phoenix">
+    <get
+      usetimestamp="true" verbose="true"
+      src="${remote.repo}/avalon-phoenix/distributions/phoenix-4.0.4-bin.zip"
+      dest="${dist.dir}/phoenix-4.0.4-bin.zip"/>
+    <unzip src="${dist.dir}/phoenix-4.0.4-bin.zip" dest="${dist.dir}" />
+    <property name="install.dir" value="${dist.dir}/phoenix-4.0.4/apps"/>
+
+    <echo message="+--------------------------------------------------------"/>
+    <echo message=": Set the environment property PHOENIX_HOME: i.e"/>
+    <echo message=": PHOENIX_HOME=${dist.dir}/phoenix-4.0.4"/>
+    <echo message=": export PHOENIX_HOME"/>
+    <echo message=":"/>
+    <echo message=": Start the server using shell scripts or bat files:"/>
+    <echo message=": ${dist.dir}/phoenix-4.0.4/bin/phoenix.sh start"/>
+    <echo message=":"/>
+    <echo message=": NOTE: On UNIX you'll need to chmod +x the shell scripts"/>
+    <echo message="+--------------------------------------------------------"/>
+  </target>
+
+	<target name="install" depends="sars,installPhoenix"
+    description="Installs into Phoenix">
+
+		<echo message="Removing older installation if any from ${install.dir}"/>
+    <delete file="${install.dir}/eve.sar"/>
+    <delete dir="${install.dir}/eve/"/>
+
+    <!-- delete older conflicting thread pool jar -->
+    <delete file="${dist.dir}/phoenix-4.0.4/lib/excalibur-thread-1.1.jar"/>
+
+    <echo message="Installing to ${install.dir}"/>
+		<copy todir="${install.dir}">
+			<fileset dir="${build.lib}">
+				<include name="eve.sar"/>
+			</fileset>
+		</copy>
+	</target>
+
+	<target name="uninstall" depends="findInstallDir"
+    description="Uninstalls from Phoenix">
+		<delete dir="${install.dir}/eve/"/>
+		<delete file="eve.sar" dir="${install.dir}"/>
+	</target>
+
+	<target name="clean" description="Cleans up artifacts from build process">
+		<delete dir="${build.dir}"/>
+		<delete dir="${dist.dir}"/>
+    <delete dir="target"/>
+		<delete dir="test"/>
+		<delete>
+			<fileset dir="." includes="**/*~" defaultexcludes="no"/>
+		</delete>
+		<delete>
+			<fileset dir="src/java/org/apache/eve/schema" 
+				includes="antlr*.*" defaultexcludes="no"/>
+		</delete>
+	</target>
+
+</project>

Added: incubator/directory/eve/branches/start/default.properties
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/default.properties	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,104 @@
+# ============================================================================
+# 				Standard Build Properties for Eve
+# ============================================================================
+# Specifies the default values for properties commonly required in ant build
+# scripts. Normally parts are overridden by ./{projectname}/default.properties
+# and/or ant.properties files. This file is not ment for editing by the 
+# average user; use ant.properties files instead
+#
+#  
+# 
+#
+
+# ----------------------------------------------------------------------------
+#           DOC GENERATION CONFIGURATION
+# ----------------------------------------------------------------------------
+# this should be overridden for each application
+
+name					= eve-server
+Name					= Eve Directory Server Project
+dir-name				= eve-server
+version					= 0.01
+package-version			= 0.01
+year					= 2002-2003
+
+# ----------------------------------------------------------------------------
+#             COMPILATION ENVIRONMENT
+# ----------------------------------------------------------------------------
+#  Settings used to configure compile environment
+
+build.debug			 	= on
+build.optimize			= off
+build.deprecation		= off
+build.compress			= false
+junit.failonerror		= false
+
+# ----------------------------------------------------------------------------
+#             DIRECTORY LOCATIONS
+# ----------------------------------------------------------------------------
+
+# ----- build destinations -----
+build.dir				= ${basedir}/build
+build.classes			= ${build.dir}/classes
+build.lib				= ${build.dir}/lib
+build.conf				= ${build.dir}/conf
+build.xdoclet			= ${build.dir}/xdoclet
+build.testsrc			= ${build.dir}/testsrc
+build.testclasses		= ${build.dir}/testclasses
+build.xdocs				= ${build.context}/content/xdocs
+build.docs				= ${build.dir}/docs
+build.javadocs			= ${build.docs}/api
+build.tests				= ${build.dir}/tests
+build.reports			= ${build.dir}/reports
+# intermediate location for documentation generation
+build.context			= ${build.dir}/documentation
+
+# ----- build sources -----
+src.dir					= ${basedir}/src
+java.dir				= ${src.dir}/java
+conf.dir				= ${src.dir}/conf
+test.dir				= ${src.dir}/test
+manifest.dir			= ${src.dir}/manifest
+xdocs.dir				= ${src.dir}/xdocs
+lib.dir					= ${basedir}/lib
+
+# ----- build distributions -----
+dist.dir				= ${basedir}/dist
+dist.javadocs			= ${dist.dir}/docs/api
+site.dir				= ${basedir}/website/build/docs/apps/
+# directory for distribution archives
+dist.base 				= ${basedir}/distributions
+
+# ----------------------------------------------------------------------------
+#                LIBRARY LOCATIONS
+# ----------------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------------
+#         REMOTE DOCUMENTATION LOCATIONS
+# ----------------------------------------------------------------------------
+# Base pointers for non-xdocs documentation. Override these in .ant.properties
+# to link to local docs
+
+avalon.base				= http://jakarta.apache.org/avalon
+framework.base			= http://jakarta.apache.org/avalon/framework
+excalibur.base			= http://jakarta.apache.org/avalon/excalibur
+phoenix.base			= http://jakarta.apache.org/avalon/phoenix
+cornerstone.base		= http://jakarta.apache.org/avalon/cornerstone
+logkit.base				= http://jakarta.apache.org/avalon/logkit
+apps.base				= http://jakarta.apache.org/avalon/apps
+testlet.base			= http://jakarta.apache.org/avalon/testlet
+
+# ----------------------------------------------------------------------------
+#                OTHER PROPERTIES
+# ----------------------------------------------------------------------------
+
+#  name of .zip/.tar.gz/.bz2 files and their top-level directory
+dist.name				= ${name}-${version}
+
+#  name of jar file
+jar.name				= ${name}-${version}.jar
+
+# which method of documetation generation to use
+documentation.tool		= cocoon
+

Added: incubator/directory/eve/branches/start/docs/issues/normalization.txt
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/docs/issues/normalization.txt	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,89 @@
+
+Problem Description:
+
+Right now normalizers are run against attribute values without considering
+some of the pathalogical forms that can be present within the value.  Schemas
+expose normalizers directly to external modules enabling them to perform
+normalization on values directly with the normalizer. This is common in
+backends that maintain their own indices or other parts of the system that
+need a cannonical representation for an attribute value.
+
+For example an attribute with a IA5CaseIgnoreMatch matching rule cannot 
+normalize regions where literal quotes are used.  Meaning it cannot lowercase 
+the literal sections or deep trim spaces from it.  It must be matched against 
+as-is even though the matching rule states otherwise.  Hence a user must put
+together filter attribute values in the same case and spacing with quotes to
+match against a literal section.  In conclusion literal value sections override matching rules.
+
+Presently cannonical representations are normalized even in literal sections
+for attribute values.  The DnParser on the otherhand correctly normalizes or
+defers normalization based on context perserving literal sections.  Indices
+on DN attributes in this respect will be inconsistent when quotes are used 
+and some searches will return more results than they should have.
+
+This potential problem is rare, depends on the data values used and requires
+the use of quotes.  It is important yet not a show stopper, but should be
+solved eventually for the sake of correctness.
+
+
+Solution:
+
+We need to parse the value and apply the normalization function associated 
+with the matching rule to non-literal sections only, concatenate normalized
+regions with literal regions and return this as the overall normalized value.
+
+So if we had an attribute 'abcxyz' where the matching rule is
+IA5CaseIgnoreMatch with the following value with boundry ticks:
+
+     1      2 3                 4 5             6
+     |      | |             | |         |
+    'cdJFAsdf \"Jack in The box\"   j AS   2345DS'
+
+would be transformed into:
+
+     1      2 3                 4 5         6
+     |      | |             | |         |
+    'cdjfAsdf \"Jack in The box\" j as 2345ds'
+
+Here segments 12 and 56 are normalized using the matching rules assigned 
+normalization funtion.  Segment 34 is untouched as a literal.  The
+transformed string is then used as an index key to lookup entries with
+this value.
+
+
+Implementation:
+
+Currently a value parser is used to correctly parse out a the values of
+DN name components optionally normalizing the values of RDN attributes 
+based on their matching rules as specified by the schema manager.  This
+parser is on in a two part parser system which together implement a 
+parser with two lexical states using a token stream switcher.  Complicating
+it further with code to merely parse a single attributes value would
+present a maintenence nightmare.  Since these parsers are antlr generated
+we can easily create a new parser which would be very simple to parse just
+attribute values which normalizing them according their matching rules
+defined in a schema.
+
+Constructing a new parser adds an extra overhead. First of all a parser 
+stores state and so must be synchronized upon.  This creates contention.
+Secondly new string objects are instantiated all over the place presenting
+a potential performance problem.  Indices manage value normalization to
+conduct searches so they can cache the most recently transformed values
+to prevent redundant normalizations accross subsystem boundries.  The same
+value may be normalized several times if it is not cached.  Also any such
+cache must be specific to an attribute to prevent value collisions in the
+cache.  Indices are the best place for caching normalized values namely 
+since the see the resultant products of normalization.  Normalizers may
+only be seeing parts of value.  In the example above a Normalizer never
+sees the complete input: it sees segments 12 and 56 without seeing segment
+34 at all.  It would store two entries total for this attribute value pair.
+The cache in an index would store one entry who's key is the original 
+value and the value is the normalized value.  This is more efficient and
+practical.
+
+Indices must then manage a cache of normalized values and use them on
+cache hits or delegate normalization requests to the schema.  The schema
+invokes a value parser with the correct normalizer for the attribute's 
+matching rule and returns the resultant normalized value.  This normalized
+value is also known as the cannonical value or simply the index key.
+

Added: incubator/directory/eve/branches/start/maven.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/maven.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,32 @@
+<project default="java:compile"
+    xmlns:j="jelly:core"
+    xmlns:u="jelly:util"
+    xmlns:ant="jelly:ant"
+    xmlns:maven="jelly:maven"
+    xmlns:m="maven"
+    xmlns:deploy="deploy">
+    
+    <preGoal name="site">
+        <attainGoal name="docbook:transform"/>
+    </preGoal>
+
+    <postGoal name="site">
+        <attainGoal name="server:copy-images"/>
+    </postGoal>
+
+    <goal name="server:copy-images">
+        <copy toDir="target/docs/images">
+            <fileSet dir="${basedir}/src/images">
+                <include name="*.gif"/>
+            </fileSet>
+        </copy>
+    </goal>
+
+    <postGoal name="antlr:generate">
+        <copy
+		file="target/antlr/org/apache/eve/schema/antlrSchemaTokenTypes.txt"
+		toDir="target/classes/org/apache/eve/schema"
+                />
+    </postGoal>
+
+</project>

Added: incubator/directory/eve/branches/start/project.properties
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/project.properties	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,16 @@
+maven.ui.banner.background=#fff
+maven.ui.source.background=#fff
+maven.ui.section.background=#6a82b6
+maven.xdoc.date=left
+maven.xdoc.version=0.7.1
+
+# Override the Modules path in build.properties
+# This defines the directory under which all of
+# the module site content will be stored.
+module.name=ldapd-server
+maven.repo.remote=http://www.ibiblio.org/maven/,http://ldapd.sourceforge.net/maven/repository/,http://cvs.apache.org/repository
+
+# antlr configuration
+maven.antlr.grammars=schema.g
+maven.antlr.src.dir=src/antlr
+

Added: incubator/directory/eve/branches/start/project.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/project.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+	xsi:noNamespaceSchemaLocation="maven-project.xsd">
+
+  <pomVersion>3</pomVersion>
+  <groupId>incubator-directory</groupId>
+  <id>eve-server</id>
+  <name>${module.name}</name>
+  <currentVersion>SNAPSHOT</currentVersion>
+
+  <developers>
+    <developer>
+      <name>Alex Karasulu</name>
+      <id>akarasulu</id>
+      <email>akarasulu at users.sourceforge.net</email>
+      <roles>
+        <role>PM</role>
+        <role>Founder</role>
+        <role>Developer</role>
+        <role>Architect</role>
+        <role>Lead Developer</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Robb Penoyer</name>
+      <id>rpenoyer</id>
+      <email>rpenoyer at users.sourceforge.net</email>
+      <roles>
+        <role>Developer</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Jim Bearce</name>
+      <id>bearcej</id>
+      <email>bearcej at users.sourceforge.net</email>
+      <roles>
+        <role>Project Manager</role>
+        <role>Developer</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Jeff Machols</name>
+      <id>jmachols</id>
+      <email>jmachols at users.sourceforget.net</email>
+      <roles>
+        <role>Developer</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Wes McKean</name>
+      <id>wesmckean</id>
+      <email>wesmckean at users.sourceforget.net</email>
+      <roles>
+        <role>Developer</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Peter Donald</name>
+      <id>donaldp</id>
+      <email>donaldp at users.sourceforge.net</email>
+      <roles>
+        <role>Advisor</role>
+        <role>Mentor</role>
+        <role>Consultant</role>
+      </roles>
+    </developer>
+
+    <developer>
+      <name>Noel Bergman</name>
+      <id>noeljb</id>
+      <email>noeljb at users.sourceforge.net</email>
+      <roles>
+        <role>Advisor</role>
+        <role>Mentor</role>
+        <role>Consultant</role>
+      </roles>
+    </developer>
+  </developers>
+    
+  <dependencies>
+	  <!-- Do we need all these dependencies?
+		log4j-core.jar
+		xdoclet-20020825.jar
+		xjavadoc-20020825.jar
+	  -->
+
+    <dependency>
+      <groupId>logkit</groupId>
+      <artifactId>logkit</artifactId>
+      <version>1.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.2</version>
+      <url>http://jakarta.apache.org/commons/logging.html</url>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.0</version>
+      <url>http://jakarta.apache.org/commons/lang</url>
+    </dependency>
+
+    <dependency>
+      <groupId>oro</groupId>
+      <artifactId>oro</artifactId>
+      <version>2.0.7</version>
+      <url>http://jakarta.apache.org/oro/index.html</url>
+    </dependency>
+
+    <dependency>
+      <groupId>jdbm</groupId>
+      <artifactId>jdbm</artifactId>
+      <version>0.12</version>
+    </dependency>
+
+    <dependency>
+      <groupId>cornerstone-threads</groupId>
+      <artifactId>cornerstone-threads-impl</artifactId>
+      <version>2.0</version>
+      <url>http://avalon.apache.org/cornerstone/</url>
+    </dependency>
+
+    <dependency>
+      <groupId>cornerstone-threads</groupId>
+      <artifactId>cornerstone-threads-api</artifactId>
+      <version>2.0</version>
+      <url>http://avalon.apache.org/cornerstone/</url>
+    </dependency>
+
+    <dependency>
+      <groupId>excalibur-thread</groupId>
+      <artifactId>excalibur-thread</artifactId>
+      <version>1.1.1</version>
+      <url>http://avalon.apache.org/excalibur/thread/index.html</url>
+    </dependency>
+
+    <dependency>
+      <groupId>avalon-phoenix</groupId>
+      <artifactId>avalon-phoenix-client</artifactId>
+      <version>4.0</version>
+      <url>http://avalon.apache.org/phoenix/</url>
+    </dependency>
+
+		<dependency>
+			<groupId>incubator-directory</groupId>
+			<artifactId>ldap-common</artifactId>
+			<version>SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
+			<groupId>incubator-directory</groupId>
+			<artifactId>ldap-snacc-provider</artifactId>
+			<version>SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
+			<groupId>commons-collections</groupId>
+			<artifactId>commons-collections</artifactId>
+			<version>2.1</version>
+			<url>http://jakarta.apache.org/commons/collections.html</url>
+		</dependency>
+
+		<dependency>
+			<groupId>regexp</groupId>
+			<artifactId>regexp</artifactId>
+			<version>1.2</version>
+			<url>http://jakarta.apache.org/regexp/index.html</url>
+		</dependency>
+
+		<dependency>
+			<groupId>antlr</groupId>
+			<artifactId>antlr</artifactId>
+			<version>2.7.2</version>
+			<url>http://antlr.org/</url>
+		</dependency>
+
+		<dependency>
+			<groupId>avalon-framework</groupId>
+			<artifactId>avalon-framework-api</artifactId>
+			<version>SNAPSHOT</version>
+			<url>http://avalon.apache.org/framework/</url>
+		</dependency>
+
+		<dependency>
+			<groupId>avalon-framework</groupId>
+			<artifactId>avalon-framework-impl</artifactId>
+			<version>SNAPSHOT</version>
+			<url>http://avalon.apache.org/framework/</url>
+		</dependency>
+
+	</dependencies>
+
+
+  <build>
+    <nagEmailAddress>directory-dev@incubator.apache.org</nagEmailAddress>
+    <sourceDirectory>${basedir}/src/java</sourceDirectory>
+    <sourceModifications/>
+    <unitTestSourceDirectory/>
+    <integrationUnitTestSourceDirectory/>
+    <aspectSourceDirectory/>
+    <unitTest/>
+  </build>
+    
+  <reports>
+    <report>maven-changelog-plugin</report>
+    <report>maven-developer-activity-plugin</report>
+    <report>maven-file-activity-plugin</report>
+    <report>maven-javadoc-plugin</report>
+		<report>maven-changes-plugin</report>
+		<report>maven-checkstyle-plugin</report>
+		<report>maven-file-activity-plugin</report>
+		<report>maven-javadoc-plugin</report>
+		<report>maven-jdepend-plugin</report>
+		<report>maven-jxr-plugin</report>
+		<report>maven-license-plugin</report>
+		<report>maven-tasklist-plugin</report>
+  </reports>
+</project>

Added: incubator/directory/eve/branches/start/sample.ant.properties
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/sample.ant.properties	Thu Jun 24 00:06:35 2004
@@ -0,0 +1 @@
+maven.repo=C:/Documents and Settings/Administrator/.maven/repository

Added: incubator/directory/eve/branches/start/sample.build.properties
==============================================================================

Added: incubator/directory/eve/branches/start/src/antlr/schema.g
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/antlr/schema.g	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,309 @@
+header {
+    package org.apache.eve.schema;
+    import java.util.* ;
+}
+
+// ===================================================
+//   TOKENS FOR LDAP SCHEMA SYNTAX LEXER DEFINITIONS
+//
+// -- (c) Apache Software Foundation                                     --
+// -- Please refer to the LICENSE.txt file in the root directory of      --
+// -- any directory project for copyright and distribution information.  --
+//
+//
+// ===================================================
+
+
+class antlrSchemaSyntaxLexer extends Lexer ;
+
+options {
+    k = 4 ;
+    exportVocab=antlrSchema ;
+    charVocabulary = '\3'..'\377' ;
+    caseSensitive = false ;
+    testLiterals = false ;
+}
+
+
+//COMMENT       : '#' (~'\n')* '\n'   
+//  ;
+
+WS  :   (   '#' (~'\n')* '\n' { newline(); }
+        |   ' '
+        |   '\t'
+        |   '\r' '\n' { newline(); }
+        |   '\n'      { newline(); }
+        |   '\r'      { newline(); }
+        )
+        {$setType(Token.SKIP);} //ignore this token
+    ;
+
+OPEN_PAREN      : '(' 
+    ;
+
+CLOSE_PAREN     : ')' 
+    ;
+
+OPEN_BRACKET    : '{' 
+    ;
+
+CLOSE_BRACKET   : '}' 
+    ;
+
+QUOTED_STRING   : '\'' ( ~'\'' )* '\'' 
+    ;
+
+AND             : '$'
+    ;
+
+OID             : 
+        ( '0'..'9' )+ ( '.' ( '0'..'9' )+ )* 
+            ( OPEN_BRACKET ('0' .. '9')+ CLOSE_BRACKET )?
+    ;
+
+IDENTIFIER options { testLiterals=true; }
+    : 
+        ( 'a' .. 'z') ( 'a' .. 'z' | '0' .. '9' | '-')*
+    ;
+
+
+class antlrSchemaParser extends Parser ;
+
+
+tokens {
+    ATTRIBUTE_TYPE          =   "attributetype"         ;
+    NAME_KW                 =   "NAME"                  ;
+    EQUALITY_KW             =   "EQUALITY"              ;
+    ORDERING_KW             =   "ORDERING"              ;
+    SYNTAX_KW               =   "SYNTAX"                ;
+    SINGLEVAL_KW            =   "SINGLE-VALUE"          ;
+    NOUSERMOD_KW            =   "NO-USER-MODIFICATION"  ;
+    USAGE_KW                =   "USAGE"                 ;
+    DESC_KW                 =   "DESC"                  ;
+    MAY_KW                  =   "MAY"                   ;
+    MUST_KW                 =   "MUST"                  ;
+    SUBSTR_KW               =   "SUBSTR"                ;
+    SUP_KW                  =   "SUP"                   ;
+    AUXILIARY_KW            =   "AUXILIARY"             ;
+    STRUCTURAL_KW           =   "STRUCTURAL"            ;
+    ABSTRACT_KW             =   "ABSTRACT"              ;
+}
+
+
+schemafile [SchemaImpl a_schema]:
+{
+    AttributeSpec l_attribute = null ;
+    ObjectClassSpec l_objectClass = null ;
+}
+    ( l_attribute=attributedef 
+        {
+            a_schema.addAttributeSpec(l_attribute) ;
+        }
+    | 
+    l_objectClass=objectclassdef 
+        {
+            a_schema.addObjectClassSpec(l_objectClass) ;
+        }
+    )+ EOF ; 
+
+
+attributedef returns [AttributeSpec l_attribute]
+{
+    l_attribute = new AttributeSpec() ;
+    ArrayList l_nameList = null ;
+}
+    :
+    ATTRIBUTE_TYPE OPEN_PAREN oid:OID l_nameList=namelist 
+        {
+            l_attribute.m_oid = oid.getText() ;
+            l_attribute.m_nameList = l_nameList ;
+        }
+        (   
+        ( "DESC" desc:QUOTED_STRING 
+            {
+                String quoted = desc.getText() ;
+                l_attribute.m_desc = quoted.substring(1, quoted.length() - 1) ;
+            }
+        ) |
+        
+
+        ( "EQUALITY" equality:IDENTIFIER 
+            {
+                l_attribute.m_equality = equality.getText().toLowerCase() ;
+            }
+        ) |
+
+
+        ( "SUBSTR" substr:IDENTIFIER
+            {
+                l_attribute.m_substr = substr.getText().toLowerCase() ;
+            }
+        ) |
+
+
+        ( "ORDERING" ordering:IDENTIFIER
+            {
+                l_attribute.m_ordering = ordering.getText().toLowerCase() ;
+            }
+        ) |
+
+
+        ( "SYNTAX" syntax:OID
+            {
+                l_attribute.m_syntax = syntax.getText() ;
+            }
+        ) |
+
+
+        ( "SINGLE-VALUE" 
+            {
+                l_attribute.m_isSingleValue = true ;
+            }
+        ) |
+
+        ( "NO-USER-MODIFICATION"
+            {
+                l_attribute.m_canUserModify = false ;
+            }
+        ) |
+
+        ( "SUP" sup:IDENTIFIER 
+            {
+                l_attribute.m_superClass = sup.getText().toLowerCase() ;
+            }
+        ) |
+
+
+        ( "USAGE" usage:IDENTIFIER
+            {
+                l_attribute.m_usage = usage.getText().toLowerCase() ;
+            }
+        )           
+        )* CLOSE_PAREN ;
+
+
+objectclassdef returns [ObjectClassSpec l_objectClass]
+{
+    l_objectClass = new ObjectClassSpec() ;
+    ArrayList l_mayList = null ;
+    ArrayList l_mustList = null ;
+    ArrayList l_superClasses = null ;
+    ArrayList l_nameList = null ;
+    
+}
+    :
+    "objectclass" OPEN_PAREN oid:OID l_nameList=namelist
+        {
+            l_objectClass.oid = oid.getText() ;
+            l_objectClass.nameList = l_nameList ;
+        }
+        (
+        ( "DESC" desc:QUOTED_STRING 
+            {
+                String tmp = desc.getText() ;
+                l_objectClass.desc = tmp.substring(1, tmp.length() - 1) ;
+            }
+        ) |
+        ( l_superClasses=superclasslist 
+            {
+                l_objectClass.superClasses = l_superClasses ;
+            }
+        ) |
+        ( "ABSTRACT" 
+            { l_objectClass.type = ObjectClassSpec.ABSTRACT   ; }
+            | "STRUCTURAL" 
+            { l_objectClass.type = ObjectClassSpec.STRUCTURAL ; }
+            | "AUXILIARY" 
+            { l_objectClass.type = ObjectClassSpec.AUXILIARY  ; }
+
+        ) |
+        ( l_mustList=mustlist 
+            {
+                l_objectClass.mustList = l_mustList ;
+            }
+        ) |
+        ( l_mayList=maylist 
+            {
+                l_objectClass.mayList = l_mayList ;
+            }
+        ) 
+        )* CLOSE_PAREN ;
+
+        
+superclasslist returns [ArrayList l_supList]
+{
+    l_supList = new ArrayList() ; 
+}
+    :
+    "SUP"  ( id:IDENTIFIER 
+        {
+            l_supList.add(id.getText().toLowerCase()) ;
+        }
+
+            | OPEN_PAREN id2:IDENTIFIER 
+        {
+            l_supList.add(id2.getText().toLowerCase()) ;
+        }
+        
+            ( AND id3:IDENTIFIER 
+
+        {
+            l_supList.add(id3.getText().toLowerCase()) ;
+        }
+        
+        )* CLOSE_PAREN ) ;
+
+
+namelist returns [ArrayList l_nameList]
+{ 
+    l_nameList = new ArrayList() ; 
+}
+    : 
+    "NAME" ( name:QUOTED_STRING 
+        {
+            String tmp = name.getText() ;
+            tmp = tmp.substring(1, tmp.length() - 1) ;
+            l_nameList.add(tmp) ;
+        }
+
+        | OPEN_PAREN (name2:QUOTED_STRING
+
+        {
+            String tmp = name2.getText() ;
+            tmp = tmp.substring(1, tmp.length() - 1) ;
+            l_nameList.add(tmp) ;
+        }
+
+            )+ CLOSE_PAREN ) ;
+
+
+
+maylist returns [ArrayList l_mayList]
+{ 
+    l_mayList = null ; 
+}
+    : "MAY" ( IDENTIFIER | l_mayList=attributelist ) ;
+
+
+
+mustlist returns [ArrayList l_mustList]
+{ 
+    l_mustList = null ; 
+}
+    : 
+    "MUST" ( IDENTIFIER | l_mustList=attributelist ) ;
+
+
+attributelist returns [ArrayList l_list]
+{ 
+    l_list = new ArrayList() ; 
+}
+    :
+    OPEN_PAREN id:IDENTIFIER 
+        { l_list.add(id.getText().toLowerCase()) ; }
+        ( AND id2:IDENTIFIER { l_list.add(id2.getText().toLowerCase()) ; })* 
+    CLOSE_PAREN ;
+
+
+
+

Added: incubator/directory/eve/branches/start/src/conf/assembly.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/conf/assembly.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,239 @@
+<?xml version="1.0"?>
+<!DOCTYPE assembly PUBLIC "-//PHOENIX/Assembly DTD Version 1.0//EN" 
+    "http://jakarta.apache.org/avalon/dtds/phoenix/assembly_1_0.dtd">
+<assembly>
+
+	<!-- ======================================================================
+
+
+
+					  C O R N E R S T O N E   B L O C K S
+
+
+
+    ======================================================================= -->
+
+
+	<!-- ======================================================================
+			  		T H R E A D   M A N A G E R   B L O C K
+    ======================================================================= -->
+
+	<block
+    		class="org.apache.avalon.cornerstone.blocks.threads.DefaultThreadManager"
+    	   	name="thread-manager"/>
+
+
+
+	<!-- ======================================================================
+
+
+
+					  S Y S T E M   M O D U L E   B L O C K S
+
+
+
+    ======================================================================= -->
+
+
+	<!-- ======================================================================
+					  O U T P U T   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.output.OutputModule"
+		name="output">
+	
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+					   I N P U T   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.input.InputModule"
+		name="input">
+
+		<provide
+			name="decoder"
+			role="org.apache.eve.decoder.Decoder" />
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+					  S C H E M A   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.schema.SchemaModule"
+		name="schema-manager"/>
+
+	<!-- ======================================================================
+				B A C K E N D   N E X U S   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.backend.NexusModule"
+		name="nexus">
+		<provide
+			name="schema-manager"
+			role="org.apache.eve.schema.SchemaManager" />
+	</block>
+
+	<!-- ======================================================================
+					L I S T E N E R   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.listener.ListenerModule"
+		name="listener">
+		<provide
+			name="client"
+			role="org.apache.eve.client.ClientManager" />
+	</block>
+
+	<!-- ======================================================================
+					  C L I E N T   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.client.ClientModule"
+		name="client">
+		<provide
+			name="decoder"
+			role="org.apache.eve.decoder.Decoder" />
+		<provide
+			name="input"
+			role="org.apache.eve.input.InputManager" />
+		<provide
+			name="output"
+			role="org.apache.eve.output.OutputManager" />
+		<provide
+			name="nexus"
+			role="org.apache.eve.backend.UnifiedBackend" />
+		<provide
+			name="protocol"
+			role="org.apache.eve.protocol.ProtocolEngine" />
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+					  E N C O D E R   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.encoder.EncoderModule"
+		name="encoder">
+
+		<provide
+			name="output"
+			role="org.apache.eve.output.OutputManager" />
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+					  D E C O D E R   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.decoder.DecoderModule"
+		name="decoder">
+		<provide
+			name="protocol"
+			role="org.apache.eve.protocol.ProtocolEngine" />
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+					 P R O T O C O L   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.protocol.ProtocolModule"
+		name="protocol">
+
+		<provide
+			name="event"
+			role="org.apache.eve.event.protocol.EventManager" />
+
+		<provide
+			name="nexus"
+			role="org.apache.eve.backend.UnifiedBackend" />
+
+		<provide
+			name="authman"
+			role="org.apache.eve.security.auth.AuthenticationManager" />
+
+		<provide
+			name="encoder"
+			role="org.apache.eve.encoder.Encoder" />
+
+		<provide
+			name="output"
+			role="org.apache.eve.output.OutputManager" />
+
+		<provide
+			name="thread-manager"
+			role="org.apache.avalon.cornerstone.services.threads.ThreadManager" />
+	</block>
+
+	<!-- ======================================================================
+			    J D B M   B A C K E N D   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.backend.jdbm.JdbmModule"
+		name="backend0">
+		<provide
+			name="schema-manager"
+			role="org.apache.eve.schema.SchemaManager" />
+		<provide
+			name="nexus"
+			role="org.apache.eve.backend.UnifiedBackend" />
+	</block>
+
+	<!-- ======================================================================
+				A U T H E N T I C A T I O N   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.security.auth.AuthenticationModule"
+		name="authman">
+		<provide
+			name="nexus"
+			role="org.apache.eve.backend.UnifiedBackend" />
+	</block>
+
+
+	<!-- ======================================================================
+				J N D I   P R O V I D E R   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.jndi.JndiProviderModule"
+		name="jndi">
+		<provide
+			name="nexus"
+			role="org.apache.eve.backend.UnifiedBackend" />
+	</block>
+
+	<!-- ======================================================================
+				E V E N T   M A N A G E R   M O D U L E   B L O C K
+    ======================================================================= -->
+
+	<block
+		class="org.apache.eve.event.protocol.EventModule"
+		name="event">
+	</block>
+
+</assembly>

Added: incubator/directory/eve/branches/start/src/conf/config.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/conf/config.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,376 @@
+<config>
+
+	<!-- ======================================================================
+    			T H R E A D   M A N A G E R   C O N F I G
+    ======================================================================= -->
+
+	<thread-manager>
+
+		<!-- Used by OutputManager for writing to client streams -->
+
+		<thread-group>
+			<name>output</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Used by InputManager for monitoring client connections -->
+
+		<thread-group>
+			<name>client</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Used by ClientManager Stage -->
+
+		<thread-group>
+			<name>clientstage</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Used for the ProtocolEngine processors and should be at least 
+			equal to the 'client' pool if not more -->
+
+		<thread-group>
+			<name>processor</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Used for the Encoder and should be at least 
+			equal to the 'client' pool if not more -->
+
+		<thread-group>
+			<name>encoder</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Used for the Decoder and should be at least 
+			equal to the 'client' pool if not more -->
+
+		<thread-group>
+			<name>decoder</name>
+			<priority>3</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>5</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+
+
+
+		<!-- Everything else -->
+		<thread-group>
+			<name>default</name>
+			<priority>2</priority>
+			<is-daemon>false</is-daemon>
+			<max-threads>4</max-threads>
+			<min-threads>1</min-threads>
+			<min-spare-threads>3</min-spare-threads>
+		</thread-group>
+	</thread-manager>
+
+
+	<!-- ======================================================================
+							S C H E M A   C O N F I G
+    ======================================================================= -->
+
+	<schema-manager>
+    	<!-- S T A G E : I  -->
+		<!-- files are parsed first to build file schemas -->
+
+    	<schema name="our"
+        	filepath="schema/our.schema" />
+    	<schema name="core"
+        	filepath="schema/core.schema" />
+    	<schema name="vendor"
+        	filepath="schema/vendor.schema" />
+    	<schema name="corba"
+        	filepath="schema/corba.schema" />
+    	<schema name="cosine"
+        	filepath="schema/cosine.schema" />
+    	<schema name="java"
+        	filepath="schema/java.schema" />
+    	<schema name="misc"
+        	filepath="schema/misc.schema" />
+
+		<!--
+    	<schema name="nis"
+        	filepath="schema/nis.schema" />
+    	<schema name="krb5-kdc"
+        	filepath="schema/krb5-kdc.schema" />
+		-->
+    	<schema name="inetorgperson"
+        	filepath="schema/inetorgperson.schema" />
+
+    	<!-- S T A G E : II  -->
+		<!-- built-ins: deepTrimToLower, deepTrim, trim, dnNormalize, asis -->
+        <!-- regex version is perl5 -->
+
+		<normalization default="asis">
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreMatch"/>
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreListMatch"/>
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreIA5Match"/>
+			<normalizer op="deepTrimToLower" rule="objectidentifiermatch"/>
+        	<normalizer op="deepTrim" rule="caseExactIA5Match"/>
+        	<normalizer op="deepTrim" rule="telephoneNumberMatch"/>
+        	<normalizer op="dnNormalize" rule="distinguishedNameMatch"/>
+
+            <normalizer rule="someNewBogusRule">
+            	<regex value="s/abc/123/g"/>
+            	<regex value="/ /d"/>
+            	<regex value="y/def/DEF/"/>
+            </normalizer>
+        </normalization>
+
+    	<!-- S T A G E : III  -->
+		<!-- built-ins: accept, . . ., TBA -->
+        <!-- regex version is perl5 -->
+		<syntax-checkers default="accept">
+        	<!-- fictitious: matches yes, Yes, YES etc -->
+			<syntax-checker oid="1.2.34.2.1.2.3.4523.1.56.4.2.34.5345.3">
+            	<regex value="/yes/i"/>
+            </syntax-checker>
+        </syntax-checkers>
+
+        <!-- S T A G E : IV  -->
+        <!-- Subschema Administrative Area Used by backend0 -->
+	    <SAA dn="dc=example,dc=com">
+	        <schema-ref schema="our"/>
+	        <schema-ref schema="core"/>
+	        <schema-ref schema="cosine"/>
+	        <schema-ref schema="corba"/>
+	        <schema-ref schema="java"/>
+	        <schema-ref schema="misc"/>
+	        <schema-ref schema="inetorgperson"/>
+        </SAA>
+    </schema-manager>
+
+
+	<!-- ======================================================================
+			A U T H E N T I C A T I O N   M A N A G E R   C O N F I G
+    ======================================================================= -->
+
+	<authman>
+	</authman>
+
+
+	<!-- ======================================================================
+				U N I F I E D   B A C K E N D   N E X U S   C O N F I G
+    ======================================================================= -->
+
+	<nexus>
+		<RootDSE>
+			<attribute name="namingContexts" value="dc=example,dc=com" />
+
+			<!-- Currently in this config there is no replica 
+			The examples below are of alternative server's that contain
+			the same naming contexts that this server contains.
+			
+			<attribute name="altServer" value="ldap://replica1:389" />
+			<attribute name="altServer" value="ldap://replica2:389" />
+			-->
+
+			<!-- Currently there are no supported extended ops
+			The extention below is RefreshRequest protocol operation defined as an
+			extention for dynamic directories see http://www.ietf.org/rfc/rfc2589.txt
+			for more information.
+
+			<attribute name="supportedExtension" value="1.3.6.1.4.1.1466.101.119.1" />
+			-->
+
+			<!-- Currently there are no supported control ops
+			These below are VLV (Virtual List View) controls and the
+			LDAP Control for a Duplicate Entry Representation of Search Results
+
+			<attribute name="supportedControl" value="2.16.840.1.113730.3.4.9" />
+			<attribute name="supportedControl" value="2.16.840.1.113730.3.4.10" />
+			<attribute name="supportedControl" value="2.16.840.1.113719.1.27.101.1" />
+			<attribute name="supportedControl" value="2.16.840.1.113719.1.27.101.2" />
+			<attribute name="supportedControl" value="2.16.840.1.113719.1.27.101.3" />
+			-->
+
+			<!-- Currently SASL is not implemented yet.
+			The following URL explains more about the SASL mechanisms used:
+			http://www.ietf.org/rfc/rfc2829.txt
+
+			<attribute name="supportedSASLMechanisms" 
+				value="ANONYMOUS PLAIN OTP DIGEST-MD5 CRAM-MD5" />
+			-->
+
+			<attribute name="subschemaSubentry" value="cn=subschema" />
+			<attribute name="supportedLDAPVersion" value="3" />
+			<attribute name="vendorName" value="ASF" />
+			<attribute name="vendorVersion" value="eve-0.01" />
+		</RootDSE>
+	</nexus>
+
+
+	<!-- ======================================================================
+						I N P U T   M O D U L E   C O N F I G
+    ======================================================================= -->
+
+	<output>
+        <stage name="output" poolname="output">
+		</stage>
+	</output>
+
+
+	<!-- ======================================================================
+						I N P U T   M O D U L E   C O N F I G
+    ======================================================================= -->
+
+	<input>
+	</input>
+
+
+	<!-- ======================================================================
+						    D E C O D E R   C O N F I G
+    ======================================================================= -->
+
+	<decoder>
+        <stage name="decoder" poolname="decoder">
+		</stage>
+	</decoder>
+
+
+	<!-- ======================================================================
+				     		E N C O D E R   C O N F I G
+    ======================================================================= -->
+
+	<encoder>
+        <stage name="encoder" poolname="encoder">
+		</stage>
+	</encoder>
+
+
+	<!-- ======================================================================
+				     P R O T O C O L   E N G I N E   C O N F I G
+    ======================================================================= -->
+
+	<protocol>
+        <stage name="protocol" poolname="processor">
+		</stage>
+	</protocol>
+
+
+	<!-- ======================================================================
+					S E R V E R   L I S T E N E R   C O N F I G
+    ======================================================================= -->
+
+		
+ 	<listener>
+		<port>1396</port>
+        <host>localhost</host>
+        <backlog>50</backlog>
+	</listener>
+
+	<!--
+ 	<listener>
+		<port>1396</port>
+        <host>172.18.9.200</host>
+        <backlog>50</backlog>
+	</listener>
+	-->
+
+
+	<!-- ======================================================================
+				C L I E N T   M A N A G E R   S T A G E   C O N F I G
+    ======================================================================= -->
+
+	<client>
+        <stage name="client" poolname="clientstage">
+		</stage>
+	</client>
+
+
+	<!-- ======================================================================
+				J D B M   B A C K E N D   ( 0 )   C O N F I G
+    ======================================================================= -->
+
+	<backend0>
+		<!-- Backend configuration properties -->
+
+
+		<!-- ==================================================================
+		Suffix Entry Definition:
+				
+			 The suffix entry is automatically created for the first time
+			 when the backend is brought up and it is not found.  If it 
+			 already exists then this section is used simply to get the
+			 Dn to the backend.
+
+		=================================================================== -->
+
+		<suffix>
+			<attribute name="distinguishedname" value="dc=example,dc=com" />
+			<attribute name="objectclass" value="top" />
+			<attribute name="objectclass" value="domain" />
+			<attribute name="dc" value="example" />
+		</suffix>
+
+		<adminUserDN>cn=admin,dc=example,dc=com</adminUserDN>
+		<adminUserPassword>jPasswordField1</adminUserPassword>
+		<workingDirPath>var/backend0</workingDirPath>
+		<entryCacheSize>1000</entryCacheSize>
+
+		<!-- Specific To Jdbm DB Backend -->
+		<indices>
+			<index name="l"/>
+			<index name="ou"/>
+			<index name="cn"/>
+			<index name="sn"/>
+			<index name="dc"/>
+			<index name="uid"/>
+			<index name="mail"/>
+			<index name="givenName"/>
+			<index name="roomnumber"/>
+			<index name="objectclass"/>
+		</indices>
+	</backend0>
+
+
+	<!-- ======================================================================
+				J N D I   P R O V I D E R   M O D U L E   C O N F I G
+    ======================================================================= -->
+
+	<jndi>
+	</jndi>
+
+
+	<!-- ======================================================================
+					E V E N T   M O D U L E   C O N F I G
+    ======================================================================= -->
+
+	<event>
+	</event>
+
+</config>

Added: incubator/directory/eve/branches/start/src/conf/environment.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/conf/environment.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<!--
+                                README!
+
+    Basic config file that sets up context for server application.
+
+
+-->
+
+<environment>
+	<logs>
+		<!--
+
+							L O G   C A T E G O R I E S
+							===========================
+
+        Note that a log <category> element's name attribute corresponds to the
+        name of the block in the assembly.xml file. Hence each block is a log
+        category in this configuration.
+
+        Also the target attribute of the <category> element is the name of the
+        <log-target> element's name attribute which determines where or rather
+        which log file we route the log event to.
+
+        -->
+
+		<category name=""
+        		  target="default"
+                  priority="DEBUG"/>
+
+		<category name="jndi"
+        		  target="jndi"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="input"
+                  target="io"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="output"
+                  target="io"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="nexus"
+                  target="backend-modules"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="backend0"
+                  target="backend-modules"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="authman"
+                  target="authentication"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="protocol"
+                  target="protocol"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="listener"
+                  target="listener"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="client"
+                  target="listener"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="schema-manager"
+                  target="schema"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="encoder"
+                  target="asn1"
+                  priority="DEBUG"/>
+
+		<category
+        		  name="decoder"
+                  target="asn1"
+                  priority="DEBUG"/>
+
+
+		<category name="event"
+        		  target="event"
+                  priority="DEBUG"/>
+
+		<!-- Logfile for Event Manager -->
+		<log-target name="event" location="/logs/event.log"/>
+
+		<!-- Logfile for Input/Output Managers -->
+		<log-target name="io" location="/logs/io.log"/>
+
+		<!-- Logfile for ASN1 BER Encoding/Decoding -->
+		<log-target name="asn1" location="/logs/asn1.log"/>
+
+		<!-- Logfile for Server Side Jndi Provider -->
+		<log-target name="jndi" location="/logs/jndi.log"/>
+
+		<!-- Logfile for server listener -->
+		<log-target name="listener" location="/logs/listener.log"/>
+
+		<!-- Logfile for backends and the backend manager -->
+		<log-target name="backend-modules" location="/logs/backends.log"/>
+
+		<!-- Logfile for the authentication module -->
+		<log-target name="authentication" location="/logs/authentication.log"/>
+
+		<!-- Logfile for the protocol server module -->
+		<log-target name="protocol" location="/logs/protocol.log"/>
+
+        <!-- Default where everything else goes -->
+		<log-target name="default" location="/logs/misc.log"/>
+
+        <!-- Schema Manager Log File -->
+		<log-target name="schema" location="/logs/schema.log"/>
+	</logs>
+
+	<policy>
+		<grant code-base="sar:SAR-INF/lib/*">
+			<permission class="java.security.AllPermission"/>
+		</grant>
+	</policy>
+
+</environment>

Added: incubator/directory/eve/branches/start/src/docbook/design/authentication-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/authentication-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: authentication-module.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:19  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/backend-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/backend-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,490 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:43:08 $</date>
+                <revdescription>
+                    <para>
+$Log: backend-module.xml,v $
+Revision 1.6  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.5  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/04/21 21:11:50  bearcej
+
+* Fix broken links in documentation.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.5  2003/03/15 17:35:24  bearcej
+Fix href to BackendInterface.gif
+
+Revision 1.1.2.4  2003/03/15 17:07:26  bearcej
+Fix figure tags to conform to simple docbook (note: maven will not handle
+correctly without a maven patch)
+Modified Files:
+ Tag: ALPHA-0_7
+    backend-module.xml
+
+Revision 1.1.2.3  2003/03/12 02:11:56  akarasulu
+Checking partial backend module docs.
+
+Revision 1.1.2.2  2003/03/11 01:26:41  akarasulu
+Started up BackendModule documentation - more to come soon.
+
+Revision 1.1.2.1  2003/03/10 23:24:19  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/10 23:12:06  akarasulu
+Moved these images to src/xdocs/design
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The BackendModule is an abstract base class which implements the
+            AtomicBackend service interface.  The abstract module provides a 
+            starting point for backend module developers.  Backend modules are 
+            the Directory Information Bases (DIB) which store entries served 
+            by the directory.  Several backends of various types may coexist 
+            within the same directory under different naming contexts.  The goal
+            of this document is to describe the server to backend contract 
+            specified by interfaces within the org.apache.eve.backend package.
+            Special emphesis will be placed on the the AtomicBackend service 
+            interface, as well as other helper interfaces and classes.  
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Architecture</title>
+        
+        <para>
+            Backends relate one to one with naming contexts exposed by the
+            server.  Backends are specialized databases customized for the 
+            storage and retieval of entries participating within a DIB's 
+            namespace.  The LDAP access model and naming model are tightly 
+            intertwined.  The interfaces defining a backend module reflect
+            the tight coupling between these models.  The operations against
+            backends fit into one of three categories: configuration parameter 
+            methods, structural DIT management operations and nCRUD entry 
+            life-cycle operations.
+        </para>
+        
+        <para>
+            Backends require interfaces to Create, Read, Update and Delete 
+            (CRUD) entries.  These operations form the basis the CRUD life-cycle
+            model for in-memory objects repeatedly retrived from and stored
+            back to disk.  For the purpose of this discussion, we refer to the
+            copy held on disk as the disk shadow copy.  It shadows the in-memory
+            image rather than mirroring it, since at any instant in time the
+            in-memory image may not be the same as the shadowed image on disk.
+            Under such circumstances the in-memory image is considered dirty.
+            The process of applying the computations used to synchronize 
+            in-memory images is called store optimization.  Store optimization
+            reverts dirty entires to clean entries.  Every backing store 
+            confronts the task of store optimization at some point.  A backend 
+            module is no exception and the exact means used to acheive 
+            synchronization is highly specific to the backing store 
+            implementation.  Regardless of the backend implementation, the 
+            architecture strives to abstract away storage mechanisms to present
+            a common entry life-cycle facade.  The use of the CRUD model 
+            achives this goal by breaking down the life-cycle into small atomic
+            operations easily implemented by encapsulating specific data 
+            storage mechanisms.
+        </para>
+        
+        <para>
+            Under CRUD, the addition of an entry to a backend requires an 
+            initial set of attributes, followed by a create operation.  The
+            create operation arguments provide the initial attribute set 
+            required to prevent a schema violation based on the entry's
+            objectclasses.  The identifiers, values and number of attributes 
+            composing the initial set vary with respect to the entry.  If the 
+            language supports variable argument lists, attribute ids and values 
+            could be provided directly as create arguments.  Better yet an 
+            empty entry object without a respective shadow copy on disk, could
+            be instanciated and populated with attributes.  The in-memory
+            entry object could then be used as the sole argument to a create 
+            operation passing in all required attributes and their values in
+            one object.  The latter approach leads to cleaner code and to a 
+            slightly altered version of the CRUD model.  Instantiation of the
+            in-memory entry shell, without a shadowed disk image, adds the
+            less central 'New' operation to CRUD.  The addition of the 'New' 
+            operation yeilds the modified CRUD or nCRUD model.  The core Backend
+            super interface supports the nCRUD entry life-cycle model by 
+            declaring the following methods:
+        </para>
+        
+        <table id="tab1">
+            <title>Supported nCRUD Operations</title>
+            <tgroup cols="5">
+                <thead>
+                    <row><entry>Method</entry>
+                    <entry>CRUD Op</entry>
+                    <entry>Source State</entry>
+                    <entry>Target State</entry>
+                    <entry>Description</entry></row>
+                </thead>
+                <tbody>
+                    <row>
+                        <entry>newEntry(String a_dn):LdapEntry</entry>
+                        <entry>New</entry>
+                        <entry>NA</entry>
+                        <entry>New</entry>
+                        <entry>
+                            Creates a new invalid LdapEntry object instance
+                            only.  Invalid entries are not shadowed in the 
+                            backing store, they are merely empty containers.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>create(LdapEntry a_entry):void</entry>
+                        <entry>Create</entry>
+                        <entry>New</entry>
+                        <entry>Clean</entry>
+                        <entry>
+                            Clean entries are valid LdapEntry object 
+                            instances that are consistant with their mirror
+                            image in the backing store.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>read(Name a_dn):LdapEntry</entry>
+                        <entry>Read</entry>
+                        <entry>NA</entry>
+                        <entry>Clean</entry>
+                        <entry>
+                            Instantiates a valid LdapEntry instance to 
+                            mirror the copy held within the backing store.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>update(LdapEntry):void</entry>
+                        <entry>Update</entry>
+                        <entry>Dirty</entry>
+                        <entry>Clean</entry>
+                        <entry>
+                            Updates the shadow copy in the backing store to
+                            mirror the in memory LdapEntry image supplied.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>delete(LdapEntry):void</entry>
+                        <entry>Delete</entry>
+                        <entry>Clean|Dirty</entry>
+                        <entry>Deleted</entry>
+                        <entry>
+                            Deletes the shadowed copy within the backing 
+                            store, and invalidates the LdapEntry argument.
+                        </entry>
+                    </row>
+                </tbody>
+            </tgroup>
+        </table>
+            
+        <para>
+            The Backend super interface declares the minimum set of operations
+            required to manage a DIB.  These methods include the nCRUD 
+            operations tabulated in Table I above.  nCRUD operations model the 
+            entry life-cycle causing transitions between entry states depicted 
+            in Figure I below.  The states are implied abstract nCRUD states.  
+            They are not necessarily modeled explicity within any 
+            implementation.
+        </para>
+        
+        <figure id="fig1">
+            <title>CRUD Life-cycle States</title>
+            <graphic fileref="../images/CRUDLifecycle.gif"/>
+        </figure>
+        
+        <para>
+            The Backend interface also declares DIB namespace management 
+            operations.  Namespace management operations affect the structure
+            of the DIB without adding or removing entries.  Name modifications 
+            upon entries occur to reflect namespace alterations.  Entry 
+            attributes other than those used for the relative distinguished 
+            name (RDN) never change.  Examples of such operations are move()
+            and modifyRdn().  Other Backend interface operations like search(), 
+            getParent(), hasEntry() and listChildren(), do not fit into either 
+            the nCRUD category nor do they fit into the catagory of namespace 
+            operations.  They are modified Read operations which enable specific
+            lookups and generalized mass Reads as DIB queries.
+        </para>
+        
+        <para>
+            The Backend super interface is extended by two sub interfaces:
+            UnifiedBackend and AtomicBackend.  Both are Avalon service 
+            interfaces.  <ulink url="http://avalon.apache.org/framework/">
+            Avalon Framework</ulink> defines the concept of a service as a
+            interface fulfilling a role within a system.  The idea leads to
+            Service Oriented Programing (SOP), which breaks a system down into 
+            a set of services.  By convention Avalon, differentiates service
+            interfaces from ordinary interfaces based on the present of a ROLE
+            constant.  The ROLE constant is a String set to the fully qualified
+            name of the service interface.  An example of a service interface
+            is shown below:
+        </para>
+        
+        <programlisting>
+            package com.calculator
+            
+            interface CalculatorService 
+            {
+                String ROLE = "com.calculator.CalculatorService" ;
+                
+                int add(int a_arg1, int a_arg2) ;
+                int sub(int a_arg1, int a_arg2) ;
+                int div(int a_arg1, int a_arg2) ;
+                int mlt(int a_arg1, int a_arg2) ;
+            }
+        </programlisting>
+        
+        <para>
+            The CalculatorService service interface exposes a set of arithmetic
+            operations accessible to other services within a system.  Note the
+            ROLE constant which is set to the fully qualified name of the 
+            interface.   Unlike this example service interface the Backend 
+            interface does not have a ROLE constant, hence it is not a service 
+            interface.  The Backend interface alone cannot be implemented by a 
+            module within the server, instead one of its sub interfaces must be
+            implemented.
+        </para>
+        
+        <para>
+            The AtomicBackend interface is a service interface according to the
+            Avalon definition with a ROLE constant set to the fully qualified
+            name of AtomicBackend: org.apache.eve.backend.AtomicBackend.  All 
+            backends
+            
+            <footnote>
+                <para>
+                    Until now we loosely referred to a naming context's DIB as 
+                    a backend and will continue to do so.  For lack of a better 
+                    term, all AtomicBackend implementations are simply referred 
+                    to as backends in lowercase.  When we specifically refer to 
+                    the Backend interface, the 'B' in Backend will be 
+                    capitalized and followed by the word 'interface'.
+                </para>
+            </footnote>
+            
+            bound to an indivisible naming context implement the 
+            AtomicBackend service interface.  Indivisible implies that all 
+            entries within the context's namespace are stored within a single 
+            DIB: an implementation of AtomicBackend.  The UnifiedBackend in 
+            contrast unifies the namespaces of all AtomicBackends under one 
+            composite Backend.  The <ulink url="nexus-module.html">NexusModule
+            </ulink> documentation discusses the UnifiedBackend service 
+            interface and its implementation in more detail.
+        </para>
+        
+        <figure id="fig2">
+            <title>Figure II: Backend Interfaces</title>
+            <graphic fileref="../images/BackendInterfaces.gif"/>
+        </figure>
+        
+        <para>
+            The interface heirarchy differentiates common DIB operations from 
+            those that are specific to the UnifiedBackend and an AtomicBackend.
+            The Backend super interface contains methods common tto both
+            services.  Inspection of <link linkend="fig2">Figure II.</link>
+            reviels the differentiating methods between the two service 
+            interfaces which consequently defines their specific roles and their
+            behavoir.  An AtomicBackend has a suffix, or naming context root 
+            specified by a (non-empty string) LDAP distinguished name.  The
+            UnifiedBackend does not.  The UnifiedBackend cannot return a suffix
+            DN if it is composed of many naming contexts.  Which context root
+            would it return?  Furthurmore, it would be redundant to have a
+            getSuffix() method on the UnifiedBackend interface since the implied
+            suffix for the UnifiedBackend is the root of all roots: the empty 
+            string DN.  The AtomicBackend inherits method declarations from the
+            BackendConfig super interface through interface polymorphism and 
+            UnifiedBackend does not.  The BackendConfig interface defines 
+            standard configuration parameters applicable only to backends that 
+            directly store entries.  Configuration parameters like isReadOnly() 
+            does not make sense for a forwarding UnifiedBackend which delegates
+            entry and namespace operations to owning AtomicBackends.  Nothing 
+            makes the distinction more apparent than the methods exposed by the 
+            UnifiedBackend which register, unregister, list, and return 
+            AtomicBackends and the context's they are bound to.
+        </para>
+            
+        <para>
+            The Backend interface is the common super interface for all 
+            services providing DIB operations like nCRUD operations and 
+            namespace operations.  It's methods alone do not constitute a 
+            service.  Our intention was to allow for two drastically different
+            backend types while making their differences transparent through
+            the common Backend super interface.  This way conversations between
+            each AtomicBackend and a caller can be routed by way of the 
+            UnifiedBackend.
+        </para>
+            
+        <para>
+            With the differences clearly outlined between the core backend
+            interfaces, let's consider their simularities and some of the
+            common helper classes involved.  Close inspection reviels the
+            throws of NamingExceptions within virtually every core backend 
+            interface.  The throws directly reflect the close relationship
+            between the LDAP access model and the LDAP naming model.  These
+            two aspects of LDAP are inseperable.  All entries are named, 
+            possesing a unique distinguished name as defined by X.500 and 
+            LDAP.  Even the call to instantiate a new entry object via newEntry
+            requires a distinguished name.  Naming is inherent to LDAP and 
+            cannot be abstracted away from an LDAP DIB.  A name is required to
+            retrieve, change or store and search for an entry.
+        </para>
+            
+        <para>
+            Up until now, most methods declared by the Backend interface have
+            been explained, yet some return types from those methods acting as
+            helper classes have not.  Namely, mass read operations or searches 
+            return a Cursor.  Before looking at how we define a Cursor as part
+            of the server to backend contract lets consider the abstract notion
+            of a cursor.  The concept obviously arose from a database server's
+            need to conserve resources.  A database server may contain far more
+            data than can fit into physical memory, and must share whatever 
+            memory resources it has across concurrent clients.  Queries have the
+            potential to return a massive amount of data to the client.  For
+            these reasons databases do not have the option of buffering query 
+            results before transmission to the client.  If they do it must be
+            at an extremely minimal level, or it must use seconday disk memory
+            to do so.  Cursors are designed to return one search candidate at
+            a time streaming results back to the client.
+            
+            require the concept of a cursor.
+            The potential of returning the contents of the entire directory 
+            tree exists.  All entries cannot possibly be loaded into memory to
+            be returned to the client at any one time with anything but trivial
+            databases.  Cursors return values one at a time without requiring
+            the entire search set to be in memory at any one time.
+        </para>
+            
+        <para>
+            BackendModule simply implements some Avalon life-cycle methods out of the box on
+            behalf of the developer trying to write a new type of backend.  Our
+            architectural focus is not restricted to this class, however it's 
+            value add will be discussed within the implementation section of 
+            this document.  For architectural and implementation specific 
+            details regarding specific backend implementations available for the
+            LDAPd server please consult the backend specific documentation.
+            Below we list the various backends available, hyperlinked to their
+            documentation sets:
+        </para>
+        
+        <itemizedlist>
+            <listitem><para>
+                <ulink url="/../../../backend-blank.html">JDBM Module
+                </ulink> - Default non-relational module using the
+                <ulink url="http://jdbm.sourceforge.net">JDBM BTree</ulink>
+                implementation.  JDBM is a Java based UNIX DBM implementation.
+            </para></listitem>
+
+            <listitem><para>
+                <ulink url="/../../../backend-blank.html">Berkeley Module
+                </ulink> - Optional module using the
+                <ulink url="http://www.sleepycat.com">BerkeleyDB</ulink> 
+                non-relational database.  BerkeleyDB is a native C database that
+                uses an API to access BTree backed binary data.
+            </para></listitem>
+
+            <listitem><para>
+                <ulink url="/../../../module-blank.html">JDBC Module
+                </ulink> - Optional module using JDBC to store entries within a
+                relational database.
+            </para></listitem>
+        </itemizedlist>
+
+        <section>
+            <title>Entry CRUD Methods And DIB Operations</title>
+            
+            <para>
+                The Backend interface specifies entry Create, Read, Update and
+                Delete (CRUD) operations and various DIB operations which don't
+                quite fit into a strictly CRUD model.  Examples of such
+                operations would be move(), search() and listChildren().  The
+                Backend interface declares the minimum set of DIB operations
+                expected from a backend.  Notice in <link linkend="fig1">Figure 
+                I</link> that all Backend interface methods throw 
+                NamingExceptions or one of its subtypes.  The CRUD specific 
+                operations are listed below in Table I and the corresponding
+                lifecycle state transitions are depicted in Figure II below it:
+            </para>
+            
+            <para>
+                The CRUD
+            </para>
+        </section>
+    </section>
+
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/client-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/client-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,496 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Client Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: client-module.xml,v $
+Revision 1.6  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.5  2003/03/26 23:02:46  jmachols
+Added changes to ClientModule implementation to bring us towards a cleaner
+session and client manager.
+
+Revision 1.4  2003/03/26 22:48:54  akarasulu
+Factored some notes back into docs given to Jeff for changes to the Client
+Manager.
+
+Revision 1.3  2003/03/26 03:53:50  jmachols
+Documenting changes and future enhancements.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:38:49  bearcej
+cvs causing problems with xml processing
+
+Revision 1.1.2.2  2003/03/15 17:08:42  bearcej
+Add abstract tags around para for abstract description.
+Modified Files:
+ Tag: ALPHA-0_7
+    client-module.xml
+
+Revision 1.1.2.1  2003/03/10 23:24:19  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/02 04:41:29  akarasulu
+*** empty log message ***
+
+Revision 1.1.2.1  2003/03/02 04:26:09  akarasulu
+ClientModule implementation document.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+    <para>
+        The ClientManager service is implemented by the ClientModule.  The
+        service is intended for client connection and hence session management.  
+        Session management plays a critical role in managing controls, user
+        profiles, authorization and the tracking of session variables.
+    </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add sequence diagrams for the handler.
+            </para></listitem>
+
+            <listitem><para>
+                Add diagrams to show some of the design concepts hit below
+                like the use of the ClientKey as a primary key, the use of
+                a thread context to pass it around etc.  Maybe a good sequence
+                diagram to show the steps to enable the storage of the ClientKey
+                within the thread context is worth while.  Drive this stuff home
+                with some diagrams because its really dry reading at the moment.
+                It puts me to sleep and I wrote it.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Design</title>
+        
+        <para>
+            Stateful protocols like LDAP maintain a client socket connection
+            through out the duration of a "session".  Several requests are 
+            issued within the scope of a session.  The socket connection
+            forms the basis to the concept of a client session.  The socket 
+            contains the IO streams and connection parameters which uniquely 
+            identify the connection.  These parameters are the client/server TCP
+            ports and the IP interfaces used to establish the connection.  
+            Connection parameters alone do not encapsulate all the information 
+            needed to complete the notion of an LDAP session.  Protocol oriented 
+            parameters specific to each client's session must be associated 
+            with the connection.  Such parameters include the identy of the
+            session owner, search controls and other operational modifiers.  As
+            stated within the objectives of the LDAPd project, we intend to 
+            provide the community with a rich LDAP application development 
+            environment on par with modern RDBMSs.  A session interface serves
+            as an exposed API, and it enables these goals by allowing user 
+            defined session variables to be read and written.  Our intent on 
+            differentiating between application, session and request scope 
+            parameters drives the design of the server and more specifically 
+            the role of the ClientManager in session state management.
+        </para>
+        
+        <para>
+            Several factors constrain our design.  Among these factors are good
+            architectural principals.  These constraints are itemized below:
+        </para>
+        
+        <itemizedlist>
+            <listitem><para>
+                Maintain a separation of concerns (SOC) to minimize coupling 
+                between subsystems.  This can be achieved by centralizing client 
+                management operations and isolating it within a single server 
+                module if possible or within the subsystem package of the 
+                module.
+            </para></listitem>
+
+            <listitem><para>
+                Recognize session management as a cross cutting aspect of any
+                stateful protocol server which counter acts SOC and increases
+                coupling.  Use design patterns to balance the affects of this 
+                pervasive aspect.
+            </para></listitem>
+            
+            <listitem><para>
+                Use the Inversion of Control (IOC) design pattern to protect
+                sensitive resources while prividing access to privledged 
+                components.
+            </para></listitem>
+
+            <listitem><para>
+                Balance these factors within a SEDA architecture with loosely
+                coupled events between stages.
+            </para></listitem>
+        </itemizedlist>
+        
+        <para>
+            The role of the ClientManager service revolves around the management
+            of clients, their connections and their session parameters.  Before
+            the introduction of core interfaces and classes used to establish 
+            the subsystem facade, the notion of a client and session requires a
+            clear definition.  To a stateful protocol server a client is a 
+            connection.  A process may posses multiple connections to the 
+            server.  Each connection regardless of the source is a client.  So
+            whether connections are made locally, from other hosts, from the
+            same process on a single host, all are treated as separate clients.
+            Each connection maintains session state on the server.  Session 
+            state stores session specific variables that are not directly 
+            related to defining or managing the connection.  For example one 
+            would not expect the identity of the authenticated user to be held
+            within a socket connection object.  The session encapsulates both
+            the connection parameters and other indirectly related session 
+            parameters.  All fall under the umbrella of a client session and are
+            inseperable.  The addition of a client implies the prior creation 
+            of a connection and the subsequent establishment of a client 
+            session.  The drop of a client implies the close of a socket 
+            connection and the destruction of the client's session.  
+            Consequently, all outstanding requests dependent on it are destroyed
+            as well.
+        </para>
+        
+        <para>
+            Design objectives revolve around the abstraction of the client and 
+            the session.  Several associations are loosely managed using a 
+            unique primary key to identify a client.  The final ClientKey class
+            defines the primary key.  It distinctly identifies a client based
+            on an identifier string constructed from connection endpoint 
+            parameters.  Clients may form connections eminating from any host
+            IP interface through any authorized port on that interface.  A 
+            server host may have multiple IP interfaces and the server process 
+            can chose to listen to any number of authorized TCP ports off those
+            interfaces.  Hence a client socket connection on the client host 
+            endpoint is defined by the IP interface and the TCP port used.  The 
+            client socket on the server side is defined by the server host's IP 
+            interface and the TCP ports of the interface on which the connection
+            is established.  Both sets of endpoint parameters are required to 
+            form a unique key distinctly identifing the client.  The primary key
+            identifier of the ClientKey is composed of these four parameters.
+        </para>
+        
+        <para>
+            Sessions and connections can be bound together using the client PK 
+            with associative tables or Maps.  The ClientSession interface 
+            defines the methods to be supported by a session entity.  
+            ClientSession implementation instances are assocated one to one with
+            a ClientKey, and a client Socket.  Depending on the object required
+            the key is used to access the respective Map to return the 
+            associated client resouce.
+        </para>
+        
+        <para>
+            The ClientKey is used as the handle on the client and its session. 
+            From it, associated objects can be looked up using ClientManager
+            methods.  Access to the key and to the ClientManager service are 
+            sufficent to apply operations affecting the state of the client
+            within the server.  For this reason every SEDA event except for the
+            ConnectEvent has a handle on the ClientKey object.  The key is 
+            passed along from stage to stage within the events.  Stage modules
+            that require the need to access client session state or affect 
+            changes to the client connection do so using this key and the 
+            ClientManager service interfaces.
+        </para>
+        
+        <para>
+            The ClientKey object is also critical for client IO synchronization 
+            within and between stages.  The OutputManager and the InputManager 
+            implementations must make sure that only one LDAP PDU is being 
+            recieved or delivered at one time.  A PDU may however be sent while
+            one is being recieved.  These requirements are accomplished by 
+            synchronizing on the ClientKey lock objects used for input and
+            output synchronization.
+        </para>
+        
+        <para>
+            The ClientKey nor the ClientSession or the ClientManager for that
+            matter, ever expose raw constructs used to manage the socket or IO
+            streams.  Meaning the actual client socket or its IO streams are not
+            accessible via API calls.  The encapsulation of the sockets and
+            its IO streams prevents tampering through public APIs.  It also
+            makes it harder for other stages to access these streams to read
+            or write to the client.  Services like the OuputManager and the 
+            InputManager need eventually to write and read from these streams
+            Application of the Inversion of Control design pattern facilitates
+            this without compromizing these sensitive resouces.  Both the 
+            InputManager and the OutputManager expose interfaces to register and
+            unregister a client socket's input and output stream respectively.  
+            The ClientManager is responsible for managing the [un]registration
+            process to enable and disable clients for IO within the server.  In
+            this respect the ClientManager controls what resources are made 
+            available to these IO managers.  It does not expose accessor methods
+            to access these IO streams by ClientKey so that IO managers can look
+            them up.  Doing so would publicly expose the streams to other 
+            unauthorized components within the server thereby bypassing 
+            encapsulation.  By passing only a stream and not the socket the 
+            ClientManager also prevents these IO services from interfering with
+            the physical socket connection.  If sockets were passed rather than
+            IO streams connected to the socket then the socket can be closed
+            without proper cleanup.  With separation of concern this is the 
+            responsibility of the ClientManager service and not that of an 
+            InputManager or an OutputManager.  Streams passed to these IO 
+            managers also need not be the socket streams.  They can instead be
+            wrapper streams that do not close the underlying data stream when
+            close operations take place.  Both managers together are responsible
+            for IO not the open or close of these connections.  Giving them the
+            power to do so would violate several design principals.  With IOC 
+            the IO managers can only mess up what they are expected to do and 
+            no more.  Other parts of the server never see these conduits to the 
+            client.  Only controlled and privledged access to these streams from
+            IO managers are possible.
+        </para>
+        
+        <para>
+            The ClientManager enables the addition of clients and the removal of
+            clients from the server using the add and drop service interfaces
+            methods.  These methods are intended to setup or tear down IO stream
+            registrations and handle session object intialization as discussed. 
+            The add method is called when a connection is initially established
+            even before a bind operation completes.  The session in this case 
+            has an LdapPrincipal with an empty yet valid Dn which connotates an
+            anonymous user.  When binding anonymously the empty string Dn is 
+            used.   The drop method is intended to close a client's connection
+            and invalidate it's ClientSession object.  The mappings used use to 
+            track the Socket by ClientKey are removed and the ClientKey is 
+            used to unregister the client's respective IO streams with both 
+            IO manager modules.  The ClientKey is also expired to prevent its 
+            use for any outstanding requests left in the stage pipeline.  Any
+            outstanding operations in progress or within the stage pipeline must
+            be terminated when the client is dropped: this is a requirement of 
+            the protocol.
+        </para>
+        
+        <para>
+            Some modules within the server are not stages so they do not recieve
+            events with payloads carrying ClientKeys.  Access to the 
+            ClientSession by way of ClientKey is only possible through method 
+            call arguments.  Between stages calls may be made by stage threads
+            to other simple modules which in turn call other simple modules.  
+            The method call chain can be very long especially if recursion is
+            used.  Having every simple module method pass in a ClientKey or 
+            ClientSession argument is impractical.  Just imagine to tunnel the
+            ClientSession down to one method it would have to be carried 
+            through multiple stack frames regardless of whether it is used in
+            the intermediate method call or not.  This would dramatically effect
+            readibility and confuse those trying to decipher the code.  
+        </para>
+        
+        <para>
+            The ClientManager service specifically confronts this issue which 
+            has the possibility of arrising in every stage of processing.  Two
+            interfaces are provided to associate and disassociate stage threads 
+            with ClientKeys.  The threadAssociate() method binds the ClientKey 
+            to the context of the calling Thread.  Subsequence calls to the no
+            argument getClientSession() method extracts the bound ClientKey 
+            from the calling Thread's context to use in a lookup that returns 
+            the associated ClientSession.  This way stages can bind the 
+            ClientKey of incomming events to the contexts of stage worker 
+            Threads right before event processing.  While stage Threads make 
+            calls to other non-staged modules synchronously in the context of
+            the stage worker Thread, the ClientKey will always accompany the
+            method call.  Simple modules use the no argument accessors to 
+            extract the ClientSession associated with the call without having
+            to pass around ClientKeys or handles to the ClientSession.  Once 
+            the stage worker Thread completes event processing it disassociates
+            the ClientKey from its context via a call to threadDisassociate()
+            on the ClientManager.  The facility is provided for all stages that
+            need to take advantage of this aspect of the service.
+        </para>
+        
+        <para>
+            With all these modules having dependencies on the ClientManager 
+            service cyclic dependencies between the ClientManager and other 
+            modules are unavoidable.  The ClientManager service in this sense
+            by far the most congested resource within the entire system.  
+            Microkernel containers like Phoenix, will not allow cyclic 
+            references between blocks or modules.  To avoid these pitfalls down
+            the road precautions were taken to define new channels through which
+            references can be made across modules in a well defined and 
+            constrained fashion without violating cyclic dependency rules within
+            an Avalon container.  Avalon uses the service method and the 
+            ServiceManager interface to facilitate the lifecycle stage where 
+            services acquire handles to other services they depend upon.  To
+            prevent the detection of true cyclic relationships between the the
+            ClientManager and other modules extra interfaces are defined.  These
+            interfaces are intended to be implemented by modules that depend on 
+            the ClientManager yet somewhere down the line the ClientManager 
+            either directly or indirectly depends on them.  So the goal is to
+            have these modules which would raise cyclic dependency errors in
+            Avalon containers obtain their backreference to the ClientManager
+            though a mechanism other than the regular Servicable life-cycle.
+            These modules should be clearly marked as imposing cyclic 
+            dependencies by way of the ClientManager.  Their access to the 
+            ClientManager service handle also needs to be controlled by the
+            ClientManager through Inversion of Control.  The ClientManager 
+            chooses who speaks to it and acts in some respect like a master 
+            module.  The dependent modules act like slaves.  The master slave
+            relationship becomes more apparent by investigating the 
+            ClientManagerSlave interface required of all modules depending on 
+            the ClientManager service.  There is one method that needs to be 
+            implemented which passes the handle to the ClientManager as the sole
+            argument.
+        </para>
+        
+        <para>
+            Up until this point we have explored the intimate details of the
+            ClientManager service role without regard to its implementation.  
+            Before going on to describe the current implementation we list the
+            responsibilities of the role:
+        </para>
+        
+        <itemizedlist>
+            <listitem><para>
+                The ClientManager ties together the various client resources 
+                composing the session of a client.  It does so through the use
+                of the unique ClientKey identifying the client.
+            </para></listitem>
+            
+            <listitem><para>
+                Add and drop methods enable control over the establishment of
+                new clients or closure to an existing client session both in 
+                respect to the socket connection and the session along with all
+                outstanding requests.  This way the service manages session 
+                creation and destruction.
+            </para></listitem>
+            
+            <listitem><para>
+                Services are provided to facilitate ClientKey propagation within
+                Thread contexts across non-staged server modules.
+            </para></listitem>
+            
+            <listitem><para>
+                The service enables a master slave relationship between itself 
+                and other dependent services to avoid cyclic dependency 
+                detection by Avalon containers.
+            </para></listitem>
+            
+        </itemizedlist>
+    </section>
+    
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            The ClientManager interface implemented by the ClientModule extends
+            the ConnectListener interface.  Hence the ClientModule must 
+            implement the methods declared within ConnectListener.  
+            ConnectListener defines a single void method, connectPerformed, 
+            which takes as its sole argument a ConnectEvent.
+        </para>
+        
+        <para>
+            The signature of the connectPerformed method does not in any way
+            impose requirements on the way the ConnectEvent processing is 
+            implemented.  The ConnectListener implementation can handle the 
+            event asynchronously or synchronously.  The ClientModule is 
+            presently implemented as a stage so the connectPerformed method
+            is implemented as a simple synchronized enqueue operation on the 
+            event queue.  Processing of the event is handled asynchronously
+            using threads from the stage thread pool to drive the event handler.
+            For more information on general stage implementation see the SEDA
+            implementation document. (Make me a link!)
+        </para>
+        
+        <para>
+            ConnectEvents deliver client socket connections to the ClientManager
+            after a successful accept call on a server listner socket.  The 
+            event is enqueued on the stage event queue.  The stage handler 
+            thread awakens to dequeue the event, and hands off the event to a 
+            stage worker thread for processing.  During processing the event's 
+            Socket is extracted, and a unique ClientKey object is generated 
+            using the properties of the client's Socket.  The ClientModule 
+            generates the ClientKey from the Socket's TCP/IP connection 
+            parameters: the client interface, the client port, the server 
+            interface and the server connection port.  The add service method
+            is then called using the ClientKey and the Socket.
+        </para>
+        
+        <para>
+            The add() method implementation makes the association between the
+            ClientKey and the Socket for subsequent lookups.  It also registers
+            the Socket's input and output streams with the respective IO 
+            manager.  The add() method called by the stage worker Thread 
+            finishes off by creating a default ClientSession object for the 
+            client.  The default session uses a user Principal synonymous with 
+            an anonymous user.  The distinguished name is the empty string for
+            this default session.  Later bind operations replace the Principal
+            with the Principal of the authenticated user.  After creating the
+            default ClientSession it is bound to the ClientKey in a Map and 
+            returned.
+        </para>
+        
+        <para>
+            The association of ClientKeys within the context of the calling 
+            thread is made using a ThreadLocal instance within the 
+            threadAssociate() method.  The association enables the lookup of 
+            the ClientSession based on the Thread of execution.  If the 
+            executing Thread is mapped to a ClientKey within the ThreadLocal 
+            object then a getClientSession() call with no arguments easily 
+            retrieves the client's session without the ClientKey.  The 
+            getClientSession() method simply looks up the ClientKey associated
+            with the caller's Thread.  After isolating the the ClientKey a 
+            lookup on the session map using the ClientKey returns the 
+            ClientSession of the calling thread.  This way we avoid passing 
+            around ClientKeys or ClientSession handles in simple modules called 
+            between stages.  Furthermore because the ClientManager is the master
+            module that all other modules can refer to, localization of session 
+            data there is ideal.
+        </para>
+        
+        <para>
+            Why have we implemented socket connection accepts using an event
+            model while making the connection close or dropping of a client a
+            matter of a simple synchronous call? Why not use a DisconnectEvent
+            and a DisconnectListener? Well, this was the case at first but we 
+            found that the operation must proceed synchronously and there was
+            no need to have a stage for this task.  Clients need to be dropped
+            as soon as an unbind request completes destroying all other requests
+            in the pipeline.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            Create InputStream and OutputStream wrappers to disable close 
+            operations on these streams by the respective IO manager.  Right 
+            now the InputModule can close the client's input stream disabling
+            a client connection.  Likewise the OutputModule can do the same with
+            the OuputStream of the client socket connection.
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            The module unnecessarily grabs a handle on the Decoder service.
+        </para>
+        
+        <para>
+            The module needs to correctly handle the change of user principals
+            by destroying all outstanding request operations and properly timing
+            out old handles to ClientKeys and ClientSessions.
+        </para>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/controls.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/controls.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,124 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Controls</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: controls.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/27 21:54:57  akarasulu
+Index exchange search control should be implemented.
+
+Revision 1.1  2003/03/27 21:34:14  akarasulu
+Start designs to implement some controls.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+    <para>
+        The LDAPv3 protocol uses controls to send and receive additional data 
+        to affect the behavior of predefined operations. Controls can be sent 
+        along with any LDAP operation to the server. These are referred to as 
+        request controls. For example, a "sort" control can be sent with an 
+        LDAP search operation to request that the results be returned in a 
+        particular order. Solicited and unsolicited controls can also be 
+        returned with responses from the server. Such controls are referred to
+        as response controls. For example, an LDAP server might define a 
+        special control to return change notifications.  LDAPv3 controls are
+        defined in section 4.1.12 of RFC <ulink url=
+        "http://www.faqs.org/rfcs/rfc2251.html">2251</ulink>. 
+    </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+
+            <listitem><para>
+                Implement special search index exchange control to redirect or
+                return entries from server with sufficent indices to rapidly
+                conduct the search.
+            </para></listitem>
+
+            <listitem><para>
+                Implement LDAP Control Extension for Server Side Sorting of 
+                Search Results, RFC 2891 
+            </para></listitem>
+
+            <listitem><para>
+                Implement LDAP Extensions for Scrolling View Browsing of Search 
+                Results, Internet-Draft Revision 4. 
+            </para></listitem>
+
+            <listitem><para>
+                Implement LDAP Proxied Authorization Control, Revision 5 
+            </para></listitem>
+
+            <listitem><para>
+                Implement LDAP Authentication Response Control, Internet-Draft 
+                Revision 1
+            </para></listitem>
+
+            <listitem><para>
+                Implement Persistent Search: A Simple LDAP Change Notification
+                Mechanism, Internet-Draft Revision 2 
+            </para></listitem>
+
+            <listitem><para>
+                Implement Manage DSA IT Control
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Design</title>
+        
+        <para>
+            Add design here.
+        </para>
+    </section>
+    
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            Add implementation details here.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            Start this stuff.
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Did not even start.
+        </para>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/decoder-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/decoder-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,258 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>DecoderModule Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:43:08 $</date>
+                <revdescription>
+                    <para>
+$Log: decoder-module.xml,v $
+Revision 1.6  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.5  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/03/25 23:17:13  akarasulu
+Finished off doc changes for use of lock objects.
+
+Revision 1.3  2003/03/24 13:22:27  akarasulu
+Made it so all modules use ClientKey lock objects for IO locking.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:24:52  bearcej
+Fixed figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    decoder-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:29  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:19  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/06 23:11:26  akarasulu
+Proof read decoder module and added some content to protocol module docs.
+
+Revision 1.1.2.1  2003/03/03 04:39:08  akarasulu
+new docs and changes
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The DecoderModule implements the Decoder service interface which is
+            a subinterface of the InputListener interface.  The InputListener 
+            interface implements a single void method called inputReceived which
+            takes an InputEvent as its sole argument.  The DecoderModule is thus
+            a glorified InputEvent listener or processor which decodes BER 
+            encoded ASN.1 LDAPv3 request message envelopes into a request 
+            LDAPMessage object.  It essentially demarshals incomming requests 
+            and is implemented as a server stage.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Have a link to the InputModule documentation.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            As mentioned in the summary, the DecoderModule must implement only 
+            one service method: inputReceived.  The InputManager which is 
+            implemented as a stage directly upstream of this Decoder stage, 
+            has input handlers that monitor client Socket InputStreams for input
+            activity.  Once input is dectected an InputEvent is generated and
+            handed off to the inputReceived method of the Decoder service.  The
+            Decoder is then responsible for reading the request PDU from the
+            stream packaged within the InputEvent.  The InputModule only detects
+            the input without interfering with or removing the content from the 
+            stream.
+        </para>
+        
+        <para>
+            The DecoderModule implements the Decoder service as a stage and so
+            its inputReceived method simply enqueues the InputEvent onto the 
+            stage event queue and returns immediately.  The event is processed
+            asynchronously by the worker threads of the DecoderModule stage 
+            using the event handler initialized within the DecoderModule's 
+            default constructor.  Events are dequeued by the stage's driver 
+            thread, and the code within the AbstractStage super class for this 
+            module creates an annonymous Runnable to wrap and drive the call to
+            the stage's EventHandler using the dequeued event.  For more details 
+            regarding stage processing see the architecture and implementation 
+            documentation for SEDA stages in LDAPd.
+        </para>
+        
+        <figure>
+            <title>DecoderModule's InputEventHandler Sequence Diagram</title>
+           <graphic fileref=
+       "../images/InputEventHandlerHandleEvent.gif"/>
+        </figure>
+        
+        <para>
+            The EventHandler for the DecoderModule is implemented as a named
+            inner class extending AbstractEventHandler.  It is responsible for
+            processing the InputEvent in its handleEvent method which takes an
+            EventObject.  The event argument must be an instance of an 
+            InputEvent.  The handleEvent method performs the work which is
+            driven by a stage worker thread.  handleEvent extracts from the 
+            InputEvent argument the ClientKey and an InputStream.
+        </para>
+        
+        <para>
+            The extracted InputStream is used to read and decode BER encoded 
+            ASN.1 LDAPv3 request message envelopes.  The DecoderModule uses a 
+            Snacc4J BERDecoder to demarshal the encoded stream bytes into an 
+            LDAPMessage request envelope object.  The Snacc4J compiler was 
+            applied to generate this LDAPMessage stub class and other classes 
+            whose instances are kept within a containment heirarchy with the
+            LDAPMessage at the root.  The Snacc4J stub compiler generated these 
+            classes from the LDAPv3 definitions specified in ASN.1 notation in 
+            <ulink url="http://www.faqs.org/rfcs/rfc2251.html"> RFC 2251</ulink> 
+            Appendix A.  The generated classes are stored within the 
+            ldapd-common subproject under the org.apache.ldap.common.ber.ldap_v3 package.
+            These classes are kept within the common subproject so that command
+            line ldap clients can be written both for protocol test suites and
+            production use.  The Snacc4J BERDecoder instance is created to 
+            specifically read from the InputStream extracted from the InputEvent
+            by invoking its constructor using the InputStream as the sole 
+            argument.  Then within a synchronized block on the input lock, the 
+            decode method of the LDAPMessage object is called using the 
+            BERDecoder instance as the sole argument.  The LDAPMessage instance 
+            was created earlier as an empty message void of content using the 
+            default constructor. Once the decode method of the LDAPMessage 
+            returns, the entire request PDU will have been read from the 
+            client's InputStream and the LDAPMessage instance will contain a 
+            tree of nested LDAPv3 defined object instances.  At this point, 
+            any further incomming bytes on the InputStream are the bytes to the 
+            next request being sent by the client.  For more info on how Snacc4J 
+            reads and decodes bytes on the InputStream to generate the 
+            LDAPMessage containment tree consult the 
+            <ulink url="http://www.alphaworks.ibm.com/tech/snaccforjava">
+            Snacc4J website</ulink>.  Since protocol engine request processors 
+            must directly access the contents within the LDAPMessage envelope,
+            the structure of the containment tree is discussed in more detail 
+            within their documentation.
+        </para>
+        
+        <para>
+            All modules must assume the possibility of concurrent access to 
+            client resources.  In the case of the Decoder another thread may
+            attempt to read from the client InputStream while a request 
+            extraction is in progress.  Concurrent access would corrupt the
+            content stream removing bytes from the PDU.  The Decoder must make
+            certain that no other thread is reading from the client's input 
+            stream from which the decoder may be in the process of demarshalling
+            a request message.  The ClientKey was explicitly designed to 
+            centralize lock objects used for inter and intra module 
+            synchronization.  Lock objects for both the client's input and 
+            output channels exist within the ClientKey.  Two separate lock 
+            objects were intentionally used to enable the writing of a response 
+            while reading requests from the client at the same time.  All 
+            modules must use these lock objects to synchronize client IO 
+            instead of using the supplied streams carried by events.  The
+            objects carried by an event may not be those used for 
+            synchronization in other modules.  Use of these lock objects 
+            instead guarrantee the use of the correct synchronization object.
+        </para>
+
+        <para>
+            Before leaving the synchronized block on the lock object, the 
+            notifyAll method is called on the input lock.  This wakes up blocked
+            threads waiting to read from the clients InputStream.  The client 
+            input monitor thread in the InputModule stage waits for this notify 
+            to resume reads on the InputStream when the decoder is finished 
+            demarshalling a request.  Finally, with the LDAPMessage populated 
+            a RequestEvent is created and packaged with the ClientKey and the 
+            demarshaled LDAPMessage.  Before returning from the handleEvent 
+            method in the InputEventHandler the generated RequestEvent is 
+            delivered to the ProtocolEngine to process the request.  The 
+            requestReceived method on the ProtocolEngine is used with the newly
+            created RequestEvent as the argument.  Upon return the worker thread
+            dies and is reclaimed by the worker thread pool of the 
+            DecoderModule stage.
+        </para>
+    </section>
+    
+    <section id="future">
+        <title>Future</title>
+        
+        <itemizedlist><listitem><para>
+            Think about writing a hard coded LDAPv3 specific encoder and decoder 
+            using our own ASN.1 parser.  The current stub compilers generate
+            stubs that implement or extend generalized encodind and decoding 
+            classes to handle any kind of notation.  This makes them less 
+            efficient but more useful.  If we hard code only for the the 
+            LDAPv3 notation and use JDK1.4 new IO libraries we can customize and
+            optimize the encoder and decoder IO handling.  Also the containment 
+            tree generated by snacc in a decoded LDAPMessage is very mesy from 
+            an OO perspective.  All members are public and intuitive accessors 
+            are not provided.  Using these generated APIs for PDU construction 
+            is tedious and the code is hard to maintain.  Also collection APIs
+            are not used in Snacc4J Java stubs.  A lot of ugliness within the 
+            protocol processors would go away if we coded explicity for the 
+            LDAPv3 definitions.  The undertaking however is an open source 
+            project on its own but well worth it considering the prevalence use
+            of ASN.1 and the BER, DER, and XER encodings.  Considering the 
+            performance impact of using direct memory IO on incoming and 
+            outgoing messages for decoding and encoding buffers gets us excited.
+        </para></listitem></itemizedlist>
+
+        <itemizedlist><listitem><para>
+            Consider the use of a2j rather than Snacc4J.  IBM's Snacc4J license 
+            according to Peter Donald is not very compatable with the Apache 1.1
+            license.  The a4j ASN.1 to Java Class compiler would better 
+            compliment the Apache License.  a2j is available 
+            <ulink url="http://sourceforge.net/projects/a2j">here</ulink>, but 
+            it may not be mature enough for now.
+        </para></listitem></itemizedlist>
+
+        <itemizedlist><listitem><para>
+            Potential use of new IO APIs to decode.  Will this be necessary
+            if channels are interchangeable or wrappable by InputStreams.  We
+            will always have to generate a DOM like containment tree of the 
+            request message to access it.  Perhaps a SAX like implementation 
+            can be found but will that be feasible with the manner in which 
+            request processors operate.  Do we want to cache copies of this 
+            data in multiple formes? Answer is no way.  Right now it is stored
+            in the LDAPMessage tree as well as parameters within the protocol
+            request processors.  It would be nice to just maintain one copy of
+            the information set stored in each request.
+        </para></listitem></itemizedlist>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <itemizedlist><listitem><para>
+            Uses Snacc4J.
+        </para></listitem></itemizedlist>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/encoder-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/encoder-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,165 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: encoder-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.4  2003/03/15 17:34:19  bearcej
+Fix href to ResponseEventHandlerHandleEvent.gif
+
+Revision 1.1.2.3  2003/03/15 17:25:35  bearcej
+Fix figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    encoder-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:30  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:19  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/09 00:36:54  akarasulu
+Finished encoder docs and refactored inner annonymous handler to be a
+named inner class.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The EncoderModule implements the Encoder service interface as a 
+            stage within the server.  It asynchronously processes ResponseEvents
+            in parallel, encoding the contents of the response message envelope
+            packaged into the ResponseEvent.  Effectively the encoder is 
+            responsible for mashaling the contents of the LDAPMessage response
+            envelope filled with Snacc4J compiler generated class instances into
+            a byte buffer.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            The Encoder service interface extends the ResponseListener interface
+            besides defining extra synchronous processing methods.  The single
+            ResponseListener method, responseComposed(), gives the staged module
+            its event processing character.  The method accepts a ResponseEvent
+            as its argument.  The implementation simply enqueues the event onto
+            the stage event queue and returns immediately.  The stage driver 
+            thread as in all stages with the server, dequeues the event and
+            dedicates a worker thread to process the event.  Again a 
+            intermediate annonymous Runnable implementation is used to have the
+            worker thread drive the call to the stage event handler.
+        </para>
+        
+        <para>
+            A single method is directly defined within the Encoder interface 
+            rather than being inherited from ResponseListener: the encode 
+            method.  The encode method is implemented by the module as a 
+            synchronous call to encode a message.  Meaning a worker thread does
+            not drive the marshaling process.  The thread of the caller drives
+            the encoding.  This synchronous version requires no event hence it
+            is not part of the ResponseListener interface but is defined 
+            directly within the Encoder interface.  The upstream need within the
+            search request processor to synchronously deliver search entry 
+            response message envelopes has resulted in this synchronous method,
+            encode.  It is only utilized within the search request processor of
+            the protocol engine module.
+        </para>
+        
+        <para>
+            Upon the dequeue of a ResponseEvent and the subsequent assignment 
+            of a worker thread to process the event within the event handler,
+            the real work of marshaling the response message envelope can be 
+            done.  A named inner class, ResponseEventHandler, is used to 
+            implement the stage event handler.  The handleEvent() method of this
+            class is used to process the ResponseEvent in the execution context
+            of a stage worker thread.  Below is a sequence diagram showing the
+            high level steps in processing the ResponseEvent within the event
+            handler.
+        </para>
+        
+        <figure>
+            <title>EncoderModule's ResponseEventHandler Sequence Diagram</title>
+            <graphic fileref="../images/ResponseEventHandlerHandleEvent.gif"/>
+        </figure>
+        
+        <para>
+            The client key of the client which generated the ResponseEvent and 
+            the response message envelope are first extracted from the event 
+            argument.  The message is encoded into a byte buffer by calling the
+            synchronous encode method.  Then the resultant marshaled PDU in the
+            byte array is used along with the client key to construct an 
+            OutputEvent.  Before the handler completes and the driving worker 
+            thread dies, the event is delivered to the downstream OutputManager
+            stage to be processed asynchronously via the writeResponse() method
+            on the OutputManager service interface.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            The same future enhancements mentioned for the decoder hold for 
+            the encoder.
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Find some faults! Believe me you they exist.
+        </para>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/event-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/event-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,343 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: event-module.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:20  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.3  2003/03/09 22:22:35  akarasulu
+For all practical purposes the EventModule documentation is considered
+done.  It is not really used yet and when it is we can fill in the
+relavent sections.
+
+Revision 1.1.2.2  2003/03/09 22:12:48  akarasulu
+Moved the event-model-chapter.xml content into the event-module.xml file.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            This chapter discusses ldapd's server side protocol event model, 
+            its use, design and implementation.  It does not cover the SEDA 
+            event model that loosely couples stages within the server.  For lack
+            of a better term we refer to this system of events, listeners and 
+            sources as the protocol event model.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>
+            Potential Uses For Pre And Post Protocol Events
+        </title>
+        
+        <para>
+            During the course of processing LDAP requests, subsystems will need 
+            to transparently inject their services.  An event model provides a 
+            decoupled way for these systems to communicate.  Listeners abstract 
+            and decouple interfaces on targets while source interfaces used to 
+            register listeners decouple the event source.  Events simply carry 
+            payloads of information required to respond appropriately.  Several 
+            subsystems will leverage the event model to transparently effect 
+            server operations without impossing dependence between themselves 
+            and other modules within the server.  This section discusses various
+            systems that would benefit from an event model.
+        </para>
+    
+        <para>
+            Authorization is an excellent candidate for using the event model.  
+            When registered for events, the authorization module will recieve 
+            events with profile information and other context information 
+            describing the operation being performed.  Of course it makes no 
+            sence to have the authorization module recieve these events after an
+            operation completes.  So it must recieve pre events to actually 
+            intervene in the process, thereby preventing unauthorized requests 
+            from being serviced.  Event delivery must notify synchronously of 
+            the pending event to allow for the authorization module to 
+            intervene.
+        </para>
+        
+        <para>
+            A trigger subsystem or module would also depend on an event model.  
+            Triggers in the RDBMS world are specified using a set of operations 
+            with a modifier used to determine when the trigger fires.  Triggers
+            this way can fire before or after an operation takes place.  
+            Triggers communicate their objections to the rest of the system by 
+            raising exceptions when conditions are not met.  Some triggers are 
+            required after an operation has completed.  Regardless of the 
+            purpose of a trigger, correct trigger operation is dependent on the 
+            receipt of events by the trigger subsystem before and after protocol 
+            operations occur.
+        </para>
+        
+        <para>
+            Master servers with replicas need to recieve entry change 
+            notification events.  Master servers contain a master replication 
+            module.  This module enqueue's change events onto the replication 
+            queues of the replication subsystem.  These events are used to 
+            asynchronously communicate the changes that need to take place to 
+            keep replica servers synchronized with master server DIB (Direcotry 
+            Information Base) changes.
+        </para>
+    </section>
+
+    <section>
+        <title>
+            Aspects Of The Protocol Event Model
+        </title>
+        
+        <para>
+            When discussing events, we need to qualify their delivery as 
+            synchronous or asynchronous.  Different situations may warrent 
+            different delivery timing requirements.  Events are triggered by 
+            event sources, then delivered to targets that posses event listener 
+            handler methods.  The design of a protocol event model requires the 
+            clear definition of the events, targets and sources involved.  These
+            concerns and their details must be explored for all conceivable use 
+            cases for the protocol event model.
+        </para>
+        
+        <para>
+            Listeners registered to receive events often need to effect the 
+            outcome of an operation based on some condition.  The authorization 
+            module is a good example of such a listener.  It must check to see 
+            if each protocol operation is allowed to proceed based on the 
+            authorization profile of the user and the parameters of the 
+            operation.  If for some reason the user is not allowed to perform 
+            the operation, the authorization subsystem must stop the operation.  
+            To stop the execution of an operation the delivery of the event must
+            occur before the operation begins.  The operation must be kept in a 
+            suspended state until the authorization module can evaluate whether 
+            access is granted or denied.  The situation requires synchronous 
+            event delivery.  If the event is delivered synchronously before the 
+            operation begins, the operation waites until the event handlers of 
+            the listeners complete - meaning until the authorization module 
+            evaluates the operation.  With synchronous deliveray a runtime 
+            authorization exception can be raised to stop the current executing 
+            thread.  The exception tunnels back up the exception stack of the 
+            driving processor thread.  The thread driver traps all exceptions 
+            reporting the reason for the failure by packaging the contents of 
+            the authorization exception into a return message to the client.
+        </para>
+    
+        <para>
+            Synchronous event delivery best suites the needs of the 
+            authorization module.  The module easily prevents an operation from 
+            executing by throwing an exception.  Because the thread executing 
+            the operation is the same thread calling the listener handlers, an 
+            exception thrown by a handler interupts the operation.  Most use 
+            cases for an event model are satisfied by a synchronous delivery 
+            mechanism.  Synchronous delivery of events can be handled 
+            asynchronously by target modules.  For example replication is best 
+            handled asynchronously.  Upon receiving an event that represents the
+            alteration of a mastered DIB the master replication module may use 
+            another thread to asynchronously push these events onto a 
+            replication event queue.  The delivery of the protocol event is 
+            synchronous yet how it is handled becomes asynchronous in the 
+            implementation replication module.  Synchronous event delivery does 
+            enable listeners to alter the outcome of an operation.  This is 
+            great if you need to affect the outcome.  This is not so good if you
+            do not want to give such power over the outcome to listener 
+            handlers.
+        </para>
+    
+        <para>
+            The power to effect the outcome or delay the outcome is given to 
+            every listener handler invoked by a processing thread.  Conditional 
+            traps can however be used to catch exceptions and ignore them, 
+            thereby allowing the operation to continue regardless of bad 
+            listener code or listener code objecting to the operation.  This 
+            would enable a finer degree of control over how much power is handed
+            off to the event handlers of registered listeners.  Modifiers that 
+            determine the mode of operation for the registered listener would be
+            part of a listener specification.  In terms of delaying the outcome,
+            there is very little that can be done outside of using processor 
+            thread controls similar to those used for search controls.  For 
+            example time limits are used to constrain a search request.  Similar 
+            constructs can be used to contstrain the maximum amount of time 
+            allowed for a thread to spend processing an event.  If the the 
+            thread spends too much time in listener event handlers the operation 
+            can be abandoned.  Again parameters used to limit the amount of time
+            a thread can spend in the listener handlers should be part of a 
+            listener specification defined perhaps at listener registration 
+            time.  Perhaps the maximum time limit can be specified based on the 
+            event type delivered instead of the listener registered.  In this 
+            case the delivery specification must be given with every event 
+            fired.  There are several ways in which the behavior of synchronous 
+            event delivery can be managed but overall synchronous event delivery 
+            is the best way to go for our internal protocol event model.
+        </para>
+    
+        <para>
+            Events can be fired from anywhere and delivered to any listener in 
+            any order.  There really is no difference between a synchronous 
+            event delivery method call and any other method call.  Event 
+            listeners simply comply with an interface for recieving a handle on
+            a constant event delivered to each listener.  These listeners are 
+            called one after the other by the same thread in a firing loop.  
+            Any module or operation in the server may initiate the firing of an 
+            event.  The firing component is logically the source of the event, 
+            in that it drove the creation of the event and triggered its 
+            delivery to the target listener interface method.  The source may 
+            be coming in from anywhere.  Obviously the protocol module can be
+            the source, the JNDI provider can also be the source when the JNDI
+            interfaces are used to make changes.  The thread used to drive the 
+            change obviously comes from the protocol module as a processor 
+            thread.  This will undoubtedly change as we begin to enable timer 
+            driven triggers in the server which are scheduled to run stored
+            procedures as a particular user.  These will be driven by a timer
+            thread or a thread from a central pool.
+        </para>
+        
+        <para>
+            Any caller to a listener handler method has the potential to be an 
+            event source.  How then do we control and manage event sources and 
+            event listeners?  We cannot and should not constrain event inducing
+            sources because the picture may change with time as parts of the 
+            server are improved.  Sources may change with server module 
+            configurations and so should be left undefined.  We should however
+            constrain listeners to implement specified interfaces.  New 
+            listeners developed can easily implement these interfaces which 
+            specify the event types listened for.
+        </para>
+        
+        <para>
+            As discussed listeners will need to register themselves with ideally 
+            the event source that generates and delivers the event.  This 
+            however need not be the case.  With many event models the source 
+            requests delivery of events to listeners using a third party which 
+            is a central fixture.  Sure listeners are registered at the source
+            for events but this need not be the case either.  A central 
+            registry can be used to act as a hub for all events generated in 
+            the server.  The registry provides interfaces for listeners to 
+            register for events.  It can also provide interfaces for firing 
+            various events on behalf of the event source.  Under such a
+            configuration we would centralize the machinery for the lookup of 
+            listeners and the delivery of events based on the event source.  
+            All the timing based requirements of event delivery and the traps 
+            used to prevent listener interference can be implemented there in
+            a central event manager.  Note once again this is separate from the 
+            asynchonous events used across server stages.
+        </para>
+        
+        <para>
+            Events are modeled to represent protocol operations.  LDAP abandon, 
+            add, bind, compare, delete, modify, modify DN, search and unbind
+            operations are represented using their own respective event types 
+            that derive from one common abstract ProtocolEvent ancestor.  The 
+            ProtocolEvent is the abstract based where common functionality or 
+            data can be added to the set of events in the model.
+        </para>
+            
+        <para>
+            Protocol operations may not directly be driving the firing of 
+            events in all cases.   Scheduled maintainence operations triggered
+            by a timer may fire events as a consequence of executing the stored
+            procedures they invoke.  These stored procedures induce changes
+            through the internal server side JNDI provider. No LDAP operation
+            recieved from a client as a PDU (Protocol Data Unit) is associated 
+            with the events fired by the executing stored procedure.  These 
+            phantom events are flagged as such via a boolean property.  This
+            property determines whether or not a physical PDU was delivered 
+            for the event.  Client operations against the server may raise 
+            triggers that fire stored procedures which operate on a DIT within
+            the server.  These indirect trigger driven changes will fire
+            events that are not associated with a physical PDU and hence will
+            have the respective flag set to false.  These events are part of 
+            the event cascade centrally rooted at the original event that 
+            started the cascade.  We need to differentiate between the root 
+            of an event cascade and all other descendent events that may fire
+            as a result of the original root event.  Protocol events are 
+            designed to keep a handle on a root event.  This way the event 
+            cascade tree can be represented using parent child associations.  
+            The parent event this way is represented as having triggered a
+            child in a cascade of event firings.  The root event of the cascade 
+            refers back to itself as the cascade root and also offers an 
+            interface to check if it is the root of the cascade this way.  In
+            both of these cases (scheduled firing and indirect cascade driven 
+            firing) no protocol activity exists yet protocol events will be 
+            fired as if a comparable protocol operation were inducing the event.
+            The event model captures all the information needed by a listener 
+            to differentiate how and why the event was fired.  By determining
+            if the event is or is not the root of a cascade and if it is
+            directly associated with a physical PDU listeners can take the
+            appropriate action after interpreting the context of the event.
+        </para>
+        
+        <para>
+            Often one event may trigger another event to be fired.  At times 
+            this will naturally result in an event cascade which may be a 
+            desirable side effect.  These cascades may result in unbounded 
+            cyclic firings within the server if listener event handlers are not
+            carefully designed.  The server must detect these dangerous
+            conditions and halt the firing of subsequent events.  Luckily since
+            synchronous delivery is used we can track the tree of events 
+            representing the event cascade by associating the structure with
+            the driving thread.  Using this tree carried with the thread of
+            execution we can determine if a cyclic firing is occuring and 
+            terminate the cascade before a StackOverflowError results.  A 
+            central event manager is perfect for placing such code to detect 
+            unbounded event cascades and managing a weak thread context hash 
+            for the event cascade tree structure.
+        </para>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            Add implementation details here.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            Add future enhancements here.
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Add faults here.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/input-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/input-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,213 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Input Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: input-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/03/24 13:22:27  akarasulu
+Made it so all modules use ClientKey lock objects for IO locking.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:11:40  bearcej
+Fixed figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    input-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:31  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:20  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/03 04:39:08  akarasulu
+new docs and changes
+
+Revision 1.1.2.1  2003/03/02 22:29:22  akarasulu
+Added input module architecture and implementation document.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The InputModule implements the InputManager service interface and in
+            doing so is responsible for detecting input on the client Socket's 
+            InputStream.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            The InputManager service interface implemented by this module 
+            defines two symetric methods for client input management.  These
+            methods are register and unregister.  The register method takes two
+            arguments: the client socket's ClientKey and its InputStream.  The 
+            unregister method takes a sole ClientKey argument to undo the 
+            affects of the register method.  Through these interface methods the
+            service provides input detection on registered client InputStreams.
+            Detection of incomming client requests results in the creation and
+            delivery of InputEvents to the request Decoder.  
+        </para>
+        
+        <para>
+            The InputModule is not a staged module.  Hence stage events can not 
+            be enqueued onto this module. Unlike a simple module it has an 
+            internal thread pool.  Pool threads execute the code which detects 
+            input on each client socket InputStream.  
+        </para>
+        
+        <para>
+            The monitoring process begins when clients are registered.  The 
+            register call first maps a ClientKey argument to an InputStream 
+            argument using a Map.  The Map enables rapid InputStream lookups 
+            based on ClientKeys.  The register method then creates and 
+            instantiates an InputStreamMonitor which happens to implement the
+            Runnable interface.  The InputStreamMonitor's run method contains 
+            the logic used to detect input on the client Socket's InputStream 
+            and is executed by threads from this module's sole thread pool.  
+            The register method, immediately before returning, assigns and 
+            starts a Thread from the pool to drive the Runnable 
+            InputStreamMonitor.  Hence an InputStreamMonitor, a driving thread,
+            and a ClientKey to InputStream Map entry are created for each 
+            registered client.
+        </para>
+        
+        <figure>
+            <title>register() Method Sequence Diagram </title>
+            <graphic fileref=
+                "../images/InputModuleRegister.gif"/>
+        </figure>
+        
+        <para>
+            The Runnable InputStreamMonitor waits blocked on a 
+            PushbackInputStream.  The PushbackInputStream wraps the client 
+            Socket's InputStream so reads from it actually read from the client.
+            The blocking call is on the read() method without arguments which 
+            returns a single byte of data from the underlying InputStream. When 
+            read() returns the byte read is pushed back to enable the decoder
+            to read a complete protocol request.  An InputEvent is created in
+            response using the ClientKey with the PushbackInputStream as event
+            members.  The InputEvent is then delivered to the Decoder service
+            which extends the InputListener interface.  The InputListener method 
+            used to deliver the event is inputReceived() which takes a sole 
+            InputEvent argument.  Once the Decorder extracts the PDU from the 
+            PushbackInputStream the monitor then loops once again to listen 
+            for incomming request PDUs.  The process continues for each request
+            PDU delivered to the client.  If the client disconnects abruptly 
+            an IOException occurs.  Once caught the client is dropped and the
+            loop terminates by returning from the run method.  Dropped clients
+            are handled by testing for key expiration or responding to a 
+            KeyExpiryException.  In either case the InputStreamMonitor's loop
+            terminates and the run method returns.
+        </para>
+        
+        <para>
+            The run() method synchronizes on the input lock object of the client
+            before going into the while loop which detects input on the stream.
+            This is necessary to prevent reads while a decoder extracts the PDU.
+            The loop makes sure that it does not reread from the stream on the 
+            same incomming PDU after input detection by sitting in a wait state.  
+            The indefinate wait() is called on the input lock object after the 
+            event is handed off to the Decoder.  The worker thread is awakened
+            to continue monitoring for input after the Decoder completes the 
+            full read of the request PDU.  The Decoder awakens the worker by
+            calling notifyAll() on the input lock object immediately after the
+            PDU read.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <itemizedlist><listitem><para>
+            Because blocking IO is used, a thread pool is needed to assign a 
+            thread to a Runnable input handler to monitor each client Socket's 
+            InputStream.  This is unavoidable with any JVM below version 1.4
+            since non-blocking IO is not provided.  JDK 1.4 introduces the new
+            IO packages that have selectable IO channels where a single thread
+            can be used to monitor multiple input channels.  For a stateful
+            protocol server non-blocking IO is critical otherwise a thread is
+            required for the management of IO on each client.  Stateful protocol
+            servers (like LDAPd) can NOT scale well as the number of concurrent 
+            clients increase.  This was a serious limitation for pure Java
+            stateful protocol servers up until JDK1.4.  Native libraries
+            could have been used while sacrificing portability but this would 
+            have problems with Java purists.  With a one to one ratio of clients
+            to threads, performance will degrade rapidly after 50 clients.
+            Non-blocking IO should allow for thousands of concurrent client 
+            connections with minimal performance hits.  Furthermore the overhead
+            of SEDA in LDAPd will not pay off until non-blocking IO is used.
+            Expect the use of NIO libraries or their equivalent in a beta 
+            release.
+        </para></listitem></itemizedlist>
+
+        <itemizedlist><listitem><para>
+            We have specifically modeled the modules dealing with client IO as
+            granular as possible to reflect a separation of concerns.  Rather 
+            than use larger modules to handle the detection and read from a 
+            stream we created two separate modules: one for IO detection and 
+            another to actually read from the client's stream.  The same
+            approach was applied with respect to the detection of client
+            connections on the server socket.  If client connection accepts,
+            input detection and input reads were bundled into one module, the
+            implementation would have been extremely trivial yet very coupled
+            and hard to manage without complete rewrites.  The listener, input, 
+            output, encoder, decoder and client modules have been defined to 
+            handle a small part of client IO management functions.  This 
+            approach should make it easier to implement plugable non-blocking 
+            replacements for most of these modules with minimal changes to their 
+            service interfaces or affecting other services associated with IO
+            management.
+        </para></listitem></itemizedlist>
+    </section>
+        
+    <section>
+        <title>Faults</title>
+        <itemizedlist>
+            <listitem><para>
+                Does not presently use non-blocking IO.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/jndi-provider-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/jndi-provider-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,169 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+	"http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+	<title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: akarasulu $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.4 $</revnumber>
+                <date>$Date: 2003/08/22 21:15:54 $</date>
+                <revdescription>
+                    <para>
+$Log: jndi-provider-module.xml,v $
+Revision 1.4  2003/08/22 21:15:54  akarasulu
+Merged changes made in the USING_PROVIDER_FRAMEWORK branch of the
+server.  I don't suspect she will be working well at this point.  Lots
+of overhauling required now.
+
+Revision 1.2.2.1  2003/05/19 00:42:41  akarasulu
+Working on getting better integration with JNDI and embedding result codes
+into the exception message strings.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:20  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+	<abstract>
+		<para>
+		</para>
+	</abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Notes</title>
+        
+        <para>
+            When the JNDI provider is used directly outside of the path through
+            the protocol module, there is no ClientKey or ClientSession 
+            associated with the thread of execution.  One cannot use the client
+            key to access the ClientSession through the ClientManager interface.
+            The identity of the user is unknown currently.  Code responsible for
+            setting the operational attributes within the UnifiedBackend or 
+            nexus as it is referred to, requires the prinicipal of the user in
+            order to set attributes like the creatorsName and the modifiersName.
+            Another means is required to establish the identity of the user on 
+            whose behalf a non-protocol engine thread executes through the JNDI
+            provider.
+        </para>
+        
+        <para>
+            JNDI inherently passes around parameters pertaining to its mode of
+            operation and to the identity of the user using environment 
+            parameters and properties.  Things like the user prinicipal and the
+            password of the user are inherited by one context which can in turn
+            lead to another.  In our particular situation calls on a Contexts 
+            and their subclasses result in calls by the server side JNDI 
+            provider to the nexus module.  These calls are made with respect to
+            a single context.  When calls are made on the nexus, the nexus
+            methods need to be able to access environment parameters without
+            passing around extra arguments.  Access to environment parameters
+            no matter how deep the calls into the nexus and its registered 
+            backends should occur on an as needed basis.  The nexus, backends
+            and other modules need to be able to differentiate between calls 
+            made by protocol module worker threads and other threads going 
+            through the JNDI provider bypassing the protocol.  
+        </para>
+        
+        <para>
+            In conclusion, every module used to conduct backend operations must 
+            first be able to differentiate between a protocol driven call and a
+            protocol bypassing call.  Secondly parameters required to conduct
+            operations must be extracted either through JNDI environment 
+            properties or through a ClientSession.  To do so threads must be 
+            tracked centrally somewhere and associated with these objects.  When
+            all operations complete or another context is used by the same 
+            thread the relationship is dismantled and another one is 
+            established.
+        </para>
+            
+        <para>
+            The ClientManager again is the perfect candidate for centrally 
+            managing thread to Context associations.  After all non-protocol 
+            driven calls through the JNDI provider are still server clients yet
+            not in the protocol sense as remote processes but in the method call
+            sense as local servers embedding LDAPd in the same process space.
+            Another reason why the ClientManager is perfect for this task is due
+            to the ability to referrence it from every module in the server.  
+            The ClientManager is the central master module.  Other modules 
+            implementing the ClientManagerSlave interface can get a handle on 
+            the ClientManager service without imposing cyclic dependencies 
+            within an Avalon Container like Phoenix.  It is the best place to 
+            keep data related to a JNDI contexts for referrence later on by 
+            modules requiring JNDI environment parameters without passing around
+            environments as arguments in each method call.
+        </para>
+        
+        <para>
+            An overload to the threadAssociate method taking a LdapContext as 
+            its only argument can be implemented to associate a thread with a 
+            JNDI LdapContext.  The context and its environment can then be 
+            referred at any time during the execution of method calls against 
+            the server's backend nexus.  The extraction of the user principal 
+            to set operational attributes simple requires a test to see if a 
+            JNDI LdapContext is associated with the calling thread.  If so the
+            environment of the context is access to get the user principal 
+            associated with the context and hence the executing thread.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/listener-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/listener-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,172 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Listener Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: listener-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:21:07  bearcej
+Fixed abstract section tag.  Fixed figure tags to conform to simple docbook
+Modified Files:
+ Tag: ALPHA-0_7
+    listener-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:32  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:21  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/09 22:14:08  akarasulu
+moved the listner.xml file to listener-module.xml
+
+Revision 1.1.2.4  2003/03/02 02:14:51  akarasulu
+Added sequence diagram for the listener thread loop.
+
+Revision 1.1.2.3  2003/03/02 00:37:31  akarasulu
+Adjusting spacing.
+
+Revision 1.1.2.2  2003/03/02 00:32:39  akarasulu
+Completed listener documentation but needs some work and added the article
+info tag to both these document.  Also flaged these docs as whitepapers.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+    <para>
+        The listener module is responsible for accepting client connections
+        on a tcp port of an ip interface.  In this sense it listens for 
+        client connections.  The module implements the ServerListener interface.
+    </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add links to other documents refered to
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            Currently the ListenerModule only supports a single server socket
+            connection and does not presently support SSL.  It is a blocking
+            implementation requiring a blocked thread on the accept() method 
+            of the ServerSocket.
+        </para>
+
+        <para>
+            The module is not a stage yet it is not a simple module as defined
+            in the architecture document.  The module is a Runnable module that
+            uses a single thread to detect client connections on the server 
+            socket.  This thread runs until the Module is stopped.  The module
+            starts the listener thread in the start stage of the module.  The 
+            thread is created fresh and started - it is not claimed from a pool.
+        </para>
+        
+        <figure>
+            <title>Listener Thread Loop Sequence Diagram</title>
+            <graphic fileref="../images/ListenerModuleRun.gif"/>
+        </figure>
+
+        <para>
+            Once started the module's driving thread enters a while loop that
+            completes when the hasStarted() status returns false for the module.
+            A call to stop() will statisfy this stop condition.  Upon entering
+            the while loop the thread blocks on the ServerSocket's accept() 
+            method until a client connection is made.  accept() returns with a
+            client Socket which is packaged into a brand new ConnectEvent.  The
+            ConnectEvent is a special ClientManager specific event.  It is a 
+            SEDA event.  Once the ListenerModule creates the ConnectEvent with
+            the Socket inside, a call is made to the ClientManager service's
+            connectPerformed() method with the event as the sole argument.  Once
+            this call completes the thread starts the loop over again providing
+            the module has not been stopped.  It is very important to make sure
+            that ClientManager implementations do not spend too much time 
+            handling the event.  The ClientModule which implements the 
+            ClientManager service interface for this reason is implemented as a 
+            stage.  The idea here is that the cost of the connectPerformed 
+            event handling operation is merely translated into a SEDA stage 
+            enqueue.  The processing is handled later asynchronously by a 
+            ClientModule worker thread.  More details are available in the SEDA
+            Stage implementation document.  The use of a stage for the 
+            ClientModule makes connection handling instantaneous allowing the
+            listener thread to immediately return to listening on the port for
+            new clients.  The inability to quickly complete a loop upon an 
+            accept() return would translate into connection latencies when the 
+            client connection frequency is high.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            This module is very primitive and will see several changes as the
+            server matures and is optimized.  At this point we see obvious 
+            changes that merely add features.  At some point before a beta the
+            module will need to support listening for client connections on 
+            multiple ports and ip interfaces.  It must also enable the use of
+            SSL while handling the nuiances to accomodate the StartTLS extended 
+            request implementation.
+        </para>
+
+        <para>
+            Beta releases will optimize the server for various JDK platforms.  
+            There is very little that can be done to optimize the module for the
+            JDK1.3 and lesser platforms however this is not the case for JDK1.4.
+            By using selectable channels we can use a single thread to listen
+            for client connections on any number of ports and ip interfaces 
+            rather than allocating a thread for each tcp port.  This provides
+            better scalability for the server as the number of ports it listens 
+            to increase.  At the end of the day however just how many ports do
+            we expect an LDAP server to be listening to.  So optimization would
+            almost be moot.  Regardless if a commital to optimizing the module
+            is made for the JDK1.4 then a JDK based swapping schema must be 
+            used to switch the implementation.  To have a single code base run
+            on both the JDK1.4 and be compatible for lesser versions, we must
+            swap selectable new IO channels for simple io at server 
+            initialization time when the JDK version can be queried from the
+            system properties.
+        </para>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/module-implementation-template.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/module-implementation-template.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: module-implementation-template.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:21  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/nexus-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/nexus-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,298 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: nexus-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:19:44  bearcej
+Fixed figure tags to confirm to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    nexus-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:32  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:21  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/10 21:44:14  akarasulu
+Done with nexus module documentation
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The NexusModule implements the UnifiedBackend service and was 
+            intended as a Backend hub or nexus for glueing together multiple 
+            naming contexts into one unified system while centralizing the 
+            management of operational attributes.  The module routes Create,
+            Read, Update and Delete (CRUD) method calls on entries as well
+            as Directory Information Base (DIB) management operations to owning 
+            Backends.  As a wrapper around all server Backends it has the unique
+            opportunity to centralize the maintanance of operational attributes 
+            for all entries before and after entry CRUD method calls and DIB 
+            management operations.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+
+
+    <section>
+        <title>Architecture</title>
+        
+        <para>
+            Breifly stated, the architectural goal is to have one central 
+            naming context independent service responsible for all Directory 
+            Information Base (DIB) operations.  Centralized DIB managment 
+            enables the transparent introduction of operational attributes in 
+            a standard manner independent of context assigned Backends.  Backend 
+            implementations need not manage operational attributes other than 
+            those specific to and required by their implementations.  Backend
+            implementation operational attribute maintenance overheads, 
+            complexity and coupling to other server modules decrease when a
+            centralized unified backend nexus service is introduced.
+        </para>
+        
+        <para>
+            The org.apache.eve.backend package within the ldapd-server subproject 
+            defines three critical interfaces to enable the aforementioned 
+            architectural goals.  The core Backend interface declares the 
+            signatures of entry CRUD operations as well as other DIB management
+            operations.  The interface does not define a ROLE constant.  The
+            primary purpose of the Backend interface is structural: 
+            implementations of this interface are not expected.  The lack of a 
+            ROLE constant revieals our intention: the Backend interface alone 
+            is insufficient for a viable backend service.  See Figure I below:
+        </para>
+        
+        <figure>
+            <title>Figure I: Backend Interfaces</title>
+            <graphic fileref="../images/BackendInterfaces.gif"/>
+        </figure>
+        
+        <para>
+            Two service interfaces are defined with a ROLE constant member: 
+            UnifiedBackend and AtomicBackend.  Implementations of these 
+            interfaces would constitute a viable service.  Both service 
+            interfaces extend from the Backend base interface.  Extention from
+            Backend implies the ability of both sub interfaces to handle entry
+            CRUD operations and DIB management operations.  These relationships
+            are depicted in the UML diagram above.
+        </para>
+            
+        <para>
+            The AtomicBackend service interface declares additional methods
+            required by concrete backends assigned as the backing store to one
+            and only one naming context.  Context specificity is implied by 
+            the getSuffix() method declaration in AtomicBackend.  Extention of
+            the BackendConfig interface by the AtomicBackend further 
+            differntiates it from the UnifiedBackend by introducing backend 
+            configuration parameter management interfaces.  As its name 
+            suggests, the AtomicBackend is clearly designed to implement an
+            indivisible backend for a single naming context specified by a
+            distinguished name suffix.  For more information see the <ulink 
+            url="backend-module.html">BackendModule</ulink> documentation.
+        </para>
+            
+        <para>
+            The UnifiedBackend service interface contains methods that 
+            differentiates its role from the AtomicBackend interface.  These
+            methods lookup, register, unregister and list AtomicBackends and 
+            the suffixes of their naming contexts.  The registration methods
+            of the interface allow the addition and removal of AtomicBackends
+            from the nexus service.  The service enables lookups of currently 
+            registered AtomicBackends through the getBackend() method which 
+            looksup AtomicBackends by suffix distinuished names.  Registered 
+            AtomicBackends or their suffixes are listed using the listBackends()
+            and listSuffixes() methods.  The interface also contains naming 
+            context independent methods.  An example would be the getRootDSE() 
+            method, which returns the Root Directory Server Agent (DSA) Entry 
+            or RootDSE.  The RootDSE resides at a nameless context and is looked 
+            up using a one level search with an empty search base distinguished 
+            name.  The unified backend is the best location for context indepent
+            entries like the RootDSE.
+        </para>
+        
+        <para>
+            Other utility methods on the UnifiedBackend provide a convenient
+            means to parse distinguished names as Strings into javax.naming.Name
+            object instances or to get a valid parser for a specific DN.  These
+            methods help present a facade to schema driven distinguished name
+            parsering.  They remove the need for modules upstream of the nexus
+            to have to interface with the SchemaManager.  The nexus hence acts
+            like a one stop service for modules like the ProtocolModule.
+        </para>
+    </section>
+    
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            The NexusModule implements the UnifiedBackend interface and extends
+            the AbstractModule base class.  The Backend interface method 
+            implementations merely wrap calls to underlying AtomicBackends after 
+            resolving a distinguished name to the owning AtomicBackend.  All 
+            Backend methods provide some manner of access to a distinguished 
+            name which localizes the operation within a specific naming context.
+            The distinguished name is either provided as an argument or can be
+            accessed from an argument passed into the method.  If the resolution
+            of a distinguished name to a registered AtomicBackend fails, the 
+            method throws the appropriate subtype of NamingException.  For these
+            reasons and others virtually all Backend interface methods throw the
+            NamingException superclass.
+        </para>
+        
+        <para>
+            Perhaps the most significant method implementations for the module
+            are those that resolve a distinguished name to a naming context, 
+            enable search traps for returning the RootDSE and configure the
+            module.  Each of these method implementations are described in the
+            paragraphs below.
+        </para>
+        
+        <para>
+            The getBackend() method resolves a distinguished name provided as a
+            javax.naming.Name argument into a naming context and returns the
+            AtomicBackend associated with the context.  The NexusModule keeps a 
+            Map of suffix distinguished names mapped as java.lang.Sting keys to 
+            AtomicBackend instances.  To lookup and return the AtomicBackend the
+            backend suffix must be extracted from Name argument.  First before
+            considerable investment, the method checks to see if the argument 
+            represents a suffix.  Next it presumes the Name argument represents
+            a non-suffix entry and cycles through all contexts looking for the
+            one whose suffix is a prefix to the Name argument.  If the loop
+            does not find a valid AtomicBackend, an IllegalArgumentException
+            is thrown.  Otherwise the AtomicBackend is returned.
+        </para>
+        
+        <para>
+            Without traping search requests, a RootDSE search would result in
+            an IllegalArgumentException in getBackend() due to the empty String
+            provided as the search base.  Remember to list the contents of the 
+            RootDSE the search base must be set to the empty string.  The nexus
+            inspects every search request to see if it needs to bypass normal
+            search processing.  Normally the nexus would forward the search 
+            request to the appropriate backend resolved using the search base.
+            Upon detection of a search with base scope and an empty string for
+            the search base, the nexus bypasses normal search processing.  It
+            creates a special Cursor which returns only one entry: the RootDSE.
+        </para>
+        
+        <para>
+            The configuration of the module simply extracts the attributes of
+            the RootDSE from the config.xml.  The attributes are stored in XML
+            using &lt;attribute&gt; tags having two manditory attributes: "name"
+            and "value".  The name attribute is used as the id of the LDAP 
+            attribute to add to the RootDSE.  The value attribute is obviously
+            used as the value of the named LDAP attribute.  These attributes are
+            used to build the RootDSE entry on the spot.  The RootDSE is a
+            special implementation of LdapEntry specifically for this purpose.
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            Enable automatic updates to the RootDSE whenever new naming contexts
+            are created or destroyed with the registration and unregistration of
+            AtomicBackends.  The namingContexts attributes would be added and 
+            removed when Backends are registered and unregistered respectively.
+        </para>
+
+        <para>
+            Enable administrative naming contexts for cn=schema and other 
+            administrative areas.
+        </para>
+        
+        <para>
+            Start managing critical operational attributes defined in RFC2251
+            for the creators name, creation timestamp or the modifiers name etc.
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Does not manage operational attributes.
+        </para>
+        
+        <para>
+            We need to reinvestigate the service interfaces implemented by this
+            module as well as AtomicBackends to find a better more JNDI like
+            mechanism for operating against a DIB.  These new interfaces should 
+            make the JNDI provider implementation trivial if designed correctly.
+            Currently, serveral transformations of an LdapEntry to an Attributes
+            object in the JNDI provider impose inefficiencies and extra code in
+            the provider.  By reducing the rift between the Backend super 
+            interface and the JNDI API methods these inefficiencies can be 
+            avoided while reducing the code base.  As a pleasent side effect,
+            upstream dependent modules can use the JNDI provider rather than 
+            access the nexus directly.  This would make those dependant modules
+            easier to understand since JNDI APIs are standard JDK APIs more 
+            familiar to most developers than the Backend, AtomicBackend, and
+            UnifiedBackend interfaces as they exist today.  Another major 
+            benefit gained from the use of the internal server side JNDI 
+            provider would be entry location transparency.  If JNDI is used 
+            references can be automatically resolved by the provider based on
+            the controls in effect.  The protocol module would not have to
+            directly invoke the Sun LDAP JNDI provider to resolve references on 
+            behalf of the user.  The server-side provider would handle 
+            references in a manner consistant with the controls bound to the 
+            ClientSession.  The protocol module would just use JNDI would little 
+            regard concerning the nature of the entries returned.  The use of 
+            the server-side JNDI provider would hence greatly simplify the 
+            implementation of the ProtocolEngine.
+        </para>
+    </section>
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/operations/opertion-template.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/operations/opertion-template.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>LDAPv3 Protocol Operation Design And Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.2 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:33 $</date>
+                <revdescription>
+                    <para>
+$Log: opertion-template.xml,v $
+Revision 1.2  2003/05/03 01:21:33  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.1  2003/03/28 05:12:35  akarasulu
+Adding documents to track changes to protocol enhancements.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Comments on Protocol Requirements</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Design</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/operations/search-operation.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/operations/search-operation.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,745 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>LDAPv3 Search Operation Design And Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.7 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:33 $</date>
+                <revdescription>
+                    <para>
+$Log: search-operation.xml,v $
+Revision 1.7  2003/05/03 01:21:33  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.6  2003/04/04 01:40:16  akarasulu
+Added more to search operation document yet temporarily suspended it to
+start working on request scope management design which all operations will
+eventually depend upon.
+
+Revision 1.5  2003/04/02 22:15:00  akarasulu
+Added section on jdbm backend design for alias dereferencing.
+
+Revision 1.4  2003/04/02 16:23:39  akarasulu
+Exploring issues dealing with alias cycles, indirect alias chains and how
+they must be handled.
+
+Revision 1.3  2003/04/02 02:15:24  akarasulu
+Got down to how we should finally handle alias dereferencing modes.
+
+Revision 1.2  2003/03/31 13:14:12  akarasulu
+Added more documentation on alias dereferencing.
+
+Revision 1.1  2003/03/28 05:12:35  akarasulu
+Adding documents to track changes to protocol enhancements.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Comments on Protocol Requirements</title>
+
+        <section>
+            <title>Aliases and Search Operations</title>
+            
+            <para>
+                Alias entries according to X.501 are entries "of the class 
+                'alias' containing information used to provide an alternative 
+                name for an object."  The objectClass definition for an alias
+                is provided below along with the attributeType definition for
+                its sole required attribute aliasedObjectName:
+            </para>
+            
+            <programlisting>
+                objectclass ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL
+                    MUST aliasedObjectName )
+            
+                attributetype ( 2.5.4.1 NAME 'aliasedObjectName'
+                    EQUALITY distinguishedNameMatch
+                    SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+            </programlisting>
+            
+            <para>
+                The aliasedObjectName is uses the distinguishedNameSyntax.
+                Aliases can only refer to entries local to the DSA since they
+                only represent distinguished names and not an LDAP URL.  There 
+                seems to be no documentation pertaining to the use of aliases 
+                that span across DIBs.  Hence we presume an alias in one backend
+                can refer to an entry within another.  Aliases cannot refer to 
+                other aliases in an alias chain according to X.501.  Write 
+                operations are not allowed to affect the DIT through aliases 
+                (need confirmation about this).  There seems to be a defunct 
+                IETF draft that never made it to RFC which discusses the 
+                expected behavoir of aliases.  See <ulink url=
+"http://www.globecom.net/ietf/draft/draft-byrne-ldap-alias-00.html">
+                draft-byrne-ldap-alias-00 </ulink> for more information 
+                regarding alias behavior in LDAPv3.  While reading this draft
+                note that it often violates RFC 2251 - namely by allowing 
+                aliases to other aliases in a chain.
+            </para>
+            
+            <para>
+                According to X.511 section 12.5.2.1 the following error codes
+                are associated with aliases (see <ulink url=
+"http://www.alternic.org/drafts/drafts-j-k/draft-just-ldapv3-rescodes-02.txt">
+                Error Code Definitons Draft</ulink> for detailed error code
+                explanations):
+            </para>
+            
+            <table frame='all'><title>Mandarory LDAPd Services</title>
+                <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+                    <colspec colname='ErrorName'/>
+                    <colspec colname='LDAPv3Code'/>
+                    <colspec colname='Description'/>
+                    <thead>
+                        <row>
+                            <entry>Error Name</entry>
+                            <entry>LDAPv3 Code</entry>
+                            <entry>Error Condition Description</entry>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <row>
+                            <entry>aliasProblem</entry>
+                            <entry>33</entry>
+                            <entry>An alias has been dereferenced which names 
+                                no object - a broken link where destination 
+                                entry does not exist. [X511, Section 12.5].
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>aliasDereferencingProblem</entry>
+                            <entry>36</entry>
+                            <entry>An alias was encountered in a situation where
+                                it was not allowed.  For example an add that 
+                                creates an alias to another alias could throw 
+                                this error or a delete operation going through
+                                an alias.  If the client does not have read 
+                                permission for the aliasedObjectName attribute 
+                                and its value then the error should be returned.
+                                [X511, Section 7.11.1.1]
+                            </entry>
+                        </row>
+                    </tbody>
+                </tgroup>
+            </table>
+            
+            <para>
+                According to section 4.5.1 of RFC 
+                <ulink url="http://www.faqs.org/rfcs/rfc2251.html">2251</ulink>,
+                search requests contain a search operation modifier called
+                derefAliases which affect the manner in which aliases are 
+                handled during the course of a search operation.  Parts of the 
+                RFC's section defining the values of the derefAliases search 
+                parameter are listed in the block below:
+            </para>
+            
+            <programlisting>
+
+            Search Request ASN.1 Notation Snippet:
+            --------------------------------------
+            
+                derefAliases    ENUMERATED {
+                        neverDerefAliases       (0),
+                        derefInSearching        (1),
+                        derefFindingBaseObj     (2),
+                        derefAlways             (3) }
+            
+            Indicator Commentary Snippet:
+            -----------------------------
+            
+            derefAliases: An indicator as to how alias objects (as defined in
+            X.501) are to be handled in searching.  The semantics of the
+            possible values of this field are:
+        
+                    neverDerefAliases: do not dereference aliases in searching
+                    or in locating the base object of the search;
+        
+                    derefInSearching: dereference aliases in subordinates of
+                    the base object in searching, but not in locating the
+                    base object of the search;
+        
+                    derefFindingBaseObj: dereference aliases in locating
+                    the base object of the search, but not when searching
+                    subordinates of the base object;
+        
+                    derefAlways: dereference aliases both in searching and in
+                    locating the base object of the search.
+                     
+            </programlisting>
+            
+            <para>
+                The definitions for the four modes of alias handling raise 
+                questions regarding alias handling behavoir.  These questions
+                deal with the order in which dereferencing and search selection 
+                criteria are applied.  If alias dereferencing is applied before
+                the application of search criteria then the filter takes affect
+                on the target entry referred to by the alias.  Conversely if
+                dereferencing is applied after the application of search 
+                criteria then the filter is applied to the alias itself and not 
+                on the target entry.  In the later case the alias may never be 
+                a candidate for dereferencing if the search filter does not 
+                select it.  Although a subtle nuance in alias handling, the 
+                order of handling can produce dramatic differences in the 
+                returned search result set.
+            </para>
+            
+            <para>
+                These questions must be answered before choosing a design 
+                approach that incorporates the handling of aliases.  The 
+                existing LDAP and DAP standards do not explicitly confront these
+                crutial details.  Perhaps the lack of standardization is the
+                reason why so many directory servers do not support aliases.
+                The SUN One Directory Server for example does not support 
+                aliases at all.  Although a sticky point aliases provide 
+                an immeasurable degree of flexibility, and should be supported.
+                Ultimately we need to pose these questions to both the LDAP and
+                DAP communities to find the appropriate answers.  For the time 
+                being some inferences can be drawn from what little information 
+                we do have regarding alias handling.  These inferences can be 
+                presented to the community for definitive answers after we draw
+                them out below.
+            </para>
+            
+            <para>
+                Let's consider alias handling for searches when the search base 
+                is an alias.  In neverDerefAliases or in derefInSearching modes 
+                the search base is never dereferenced.  Hence it must be treated
+                like any other regular leaf entry.  Depending on the search 
+                scope and the filter used there are two possible outcomes: 
+                either nothing is returned or the search base entry (the alias)
+                is returned.  Regardless of the filter used, a search scope set 
+                to one level search will always return nothing.  One level 
+                scoped searches never return the search base entry in the result
+                set.  If base level or subtree level search scope is used, then 
+                the alias is returned in the result set only if the search 
+                filter selects the base (alias) entry.  For example a filter of
+                '(objectClass=alias)' will select the alias entry when the 
+                search scope is set to the base or subtree level scope.  If the
+                alias entry is to be returned it is packaged in a 
+                SearchResultEntry PDU and sent to the client.  A final 
+                SearchResultDone PDU signals the completion of the search 
+                operation.  If the alias is not selected a single 
+                SearchResultDone PDU only.
+            </para>
+                
+            <para>    
+                If a search request has derefAliases set to derefAlways or 
+                derefFindingBaseObj then the search base if it is an alias is 
+                dereferenced before the search filter is applied.  The effective
+                search base then becomes the DN of the entry pointed to by the 
+                alias.  In these cases alias, dereferencing of the base must be 
+                applied before the search begins.  Use of the aliased DN 
+                propagates it to the new search base.  Ironically the previous 
+                filter example '(objectClass=alias)' using the base search scope 
+                should return nothing in these modes which do dereference the
+                base entry.  The reason being is the dereferenced base cannot 
+                be an alias since chaining is not allowed.  So once the new base
+                is dereferenced, and the filter is applied, the filter 
+                expression will not select it.  Based on the position of the 
+                new search base, the search scope, and the search filter the 
+                returned result set could be just about anything.  We can only 
+                comment on this one special filter example's result.
+            </para>
+                
+            <para>
+                Search behavoir under these cases enabling search base 
+                dereferencing are well understood and documented.  It is clear
+                in these cases that dereferencing of aliases must occur before
+                the application of search filters to select dereferenced entries
+                and their descendants.  Standards however lack clarity with 
+                regard to search behavoir when alias dereferencing is totally 
+                enabled while searching.  To obtain a solid footing we have 
+                decided to take a leap of faith with a simple presumption 
+                regarding alias handling consistancy.  The presumption stems 
+                from our clear conclusions regarding the order of dereferencing
+                found for alias handling on search bases.  In this light, we 
+                presume the consistant application of alias dereferencing 
+                before the application of search criteria across all alias 
+                handling modes.  So with this premis, derefInSearching mode on 
+                a subtree scoped search would dereference every descendant 
+                alias under the search base whether or not the search filter 
+                selects descendant alias entries.  The impact of this premis 
+                aligns perfectly well with search semantics and the concept of 
+                name aliases.  Aliases alter both the DIT structure and the 
+                namespace by providing alternative names for entries.  In 
+                affect, under the various modes of alias handling they present 
+                different views of the DIT to search operations.  When aliases 
+                are never dereferenced the DIT remains a perfect tree structure 
+                with aliases represented as leaf entries.  Without 
+                dereferencing, aliases have no influence on the effective 
+                namespace presented to a search operation.  When alias
+                dereferencing is totally enabled, the effective DIT structure 
+                and namespace, which a search filter operates on, differs from
+                modes where alias dereferencing is totally disabled.  The 
+                alternative view of the DIT structure and namespace represents 
+                aliased names and alias induced structural relationships as 
+                actual entry names and relationships as if aliases never 
+                existed in the first place.  The new modifed view of the DIT, 
+                depending on the aliases used, may be a tree or it may be a
+                graph.  Regardless the search algorthim which applies the filter
+                to the DIB, should operate on the modified view when alias 
+                dereferencing has been totally enabled.
+            </para>
+                
+            <para>
+                In conclusion, all alias handling modes, if at all, must 
+                dereference aliases before applying search filters to select
+                DIT entries.  This clarifies our approach in dealing with the
+                two modes: derefInSearching and derefAlways.  derefAlways after 
+                the initial search base is dereferenced reduces to the 
+                derefInSearching mode by using the DN of entry referenced by the
+                alias.  After this step the handling of these modes are the 
+                same.  To conduct searches in derefAlways and derefInSearching 
+                modes the alias dereferencing mechanism is unfortunately 
+                optimally implemented within a backend module's search algorthm 
+                to enable dereferencing before the application of search 
+                criteria.  This is unfortunate because it demands the knowledge
+                of alias handling behavoir on the part of backends and their 
+                implementors.
+            </para>
+            
+            <para>
+                Another potential pitfall while dereferencing aliases during
+                searches with subtree scope appears when aliases induce cycles
+                within the DIT.  Cycles cause infinite loops or the return
+                of redundant entry copies to the client.  A simple cycle
+                results when an alias refers back to a relative within the 
+                heirarchy.  Dereferencing the alias to propagate the search back
+                at the relative eventually encounters the alias once again and
+                so on in an infinite search loop.  One approach to mitigate the
+                problem would be to restrict alias creation, by rejecting the
+                addition of aliases to the DIT which cause cycles where the
+                offending alias refers back to an immediate or distant parent.
+                Another approach would be to track search propagation preventing
+                the dereferencing of aliases more than once.  Although the 
+                approach prevents an infinite loop it does not prevent the
+                possibility of returning duplicate entry copies to the client.
+                The search would have to track the entries it has already 
+                returned to prevent the redundant return of duplicates.
+            </para>
+            
+            <para>
+                More complex situations occur where indirect alias chains cause 
+                cycles.  When refering to indirect chains we do not mean the 
+                referral of one alias to another.  This is not allowed to begin
+                with.  Indirect chains occur when one alias refers to an entry,
+                which has a descendant alias that refers back to a parent of the
+                first alias.  Under a subtree scoped search with dereferencing 
+                enabled, the search would eventually cycle from the first alias
+                to the second and back to the first.  This "indirect chain" 
+                presents the same challanges encountered in a simple cyclic
+                alias.  The chain however is much harder to detect and its 
+                affects are less trivial to handle than the simple cycle 
+                inducing alias.  These problems must be confronted regardless
+                of the design approach.
+            </para>
+            
+            <para>
+                With respect to JNDI, alias dereferencing is controled using the
+                "java.naming.ldap.derefAliases" environment property.  The 
+                "dereference links" flag obtained via the getDerefLinkFlag() on
+                SearchControls has nothing to do with alias dereferencing.  
+                This is clearly stated in the tutorial for JNDI.  However, the
+                flag's purpose is unknown due to lack of documentation by SUN.  
+                Can someone find out what it's used for?  Also when resolving 
+                the name of an aliased entry using the NameClassPair method 
+                getName() on dereferenced aliases, the name returned will be the 
+                full distinguished name of the aliased entry and not the 
+                relative distinguished name.  As a consequence the isRelative()
+                method for the NameClassPair should return false.  This nuance 
+                yet a requirement of JNDI must be meet by the server side JNDI 
+                provider once alias dereferencing is enabled.
+            </para>
+        </section>
+    </section>
+    
+    <section>
+        <title>Design</title>
+        
+        <section>
+            <title>Alias Handling in Search Operations</title>
+            
+            <para>
+                With some of our conclusions in the protocol commentary section
+                above regarding alias handling, we now consider some design 
+                approaches in this section.  These approaches are dependent on 
+                the existing server design and so we breifly recap its relavent
+                aspects.
+            </para>
+            
+            <para>
+                The search operation is conducted within the ProtocolModule
+                using a search request processor.  The processor extracts search
+                parameters from the SearchRequest PDU and calls the search 
+                method on the nexus to return a Cursor over the result set.  The
+                processor then enters a loop to pull entries one at a time from 
+                the backend using the search Cursor.  Each iteration transmits
+                an entry packaged within a SearchResultEntry PDU to the client.
+                The Cursor returned by the search method of the nexus, is 
+                actually created by calling the search method on the backend 
+                associated with the naming context of the search base.  In this 
+                respect the nexus design presumes the confinement of a search 
+                operation to a single backend.  The current nexus design 
+                presents challanges for alias dereferencing when aliases in one
+                backend refer to entries in other backends.  "DIB crossing 
+                aliases", as we coin them, may require a completely different 
+                approach to handling dereferencing.
+            </para>
+                
+            <para>
+                With the design in mind we now explore the design options
+                for the various alias dereferencing modes.  Without alias
+                dereferencing support the server effectively operates in
+                neverDerefAliases mode.  The alias is returned itself within a
+                SearchResultEntry PDU as if it is a terminal leaf entry.
+                derefFindingBaseObj mode could be handled trivially before
+                calling search on the nexus within the search processor.  Search
+                base dereferencing can also be handled within the nexus itself.
+                In these cases, the search base entry could be checked to see
+                if it is an alias.  If it is an alias the target entry it points
+                to could be dereferenced and used as the base of the search when
+                the call to the nexus or owning backend is made.  The amount of
+                change required to enable this mode is trivial with several
+                implementation alternatives.
+            </para>
+            
+            <para>
+                The other two modes, derefInSearching and derefAlways, would
+                require non-trivial changes to handle alias dereferencing since
+                they pervade into the searching mechanism.  Requirin the
+                dereferencing of aliases before the application of search
+                selection criteria, tightly couples dereferencing with the
+                search algorithm.  In an effort to simplify our approach, we
+                reduce the two modes into one.  As mentioned before the only
+                difference between derefInSearching and derefAlways modes is
+                the fact that the search base if it is an alias is resolved
+                before the search.  So for all practical purposes we can reduce
+                the derefAlways mode into the derefInSearching mode by
+                dereferencing the search base to the aliased DN.  Then the
+                dereferenced entry can then be used as the search base while
+                conducting the search as if it were in derefInSearching mode.
+                Even with this reduction, derefInSearching mode is not a simple
+                mode to manage especially with whole subtree scoped searches.
+                Many approaches can be taken for dereferencing aliases when in
+                derefInSearching mode.  We shall explore the options within the
+                rest of this section to determine the most optimal design for
+                searches conducted in derefInSearching mode.  All options below
+                are geared specifically to the toughest case to handle: a
+                search in derefInSearching mode with the scope set to the whole
+                subtree.
+            </para>
+            
+            <section>
+            <title>Alias Handling Outside of Backends</title>
+            
+            <para>
+                Already congested Backends can be spared by embedding alias 
+                dereferencing fuctionality into the protocol engine's search 
+                request processor or into the nexus module.  While iterating 
+                through the resultant cursor the search processor may encounter 
+                aliased entries.  On an alias entry the processor can conduct a 
+                subordinate search using the DN of the aliased entry as the 
+                search base with the parent search's parameters.  Once a 
+                subordinate search cursor is consumed the parent search can 
+                carry on from where it left off.
+            </para>
+            
+            <para>
+                This approach has several problems.  The the most apparent lies
+                in the fact that a subordinate search may return yet another
+                alias and its subordinates may in turn return more aliases and 
+                so on.  A recursive solution would be required to resolve the 
+                possible heirarchy of alias triggered subordinate searches.  A 
+                special cursor can be designed to encapsulate the process and 
+                lessen the amount of impact this would produce on the regions 
+                responsible for alias dereferencing.  At some point during the 
+                search the number of subordinate search cursors waiting for the 
+                last cursor in the chain to complete will be equal to the depth
+                of the deepest alias chain in the search.  That is if there are 
+                no time or size limitations.  Furthermore there is the danger 
+                of cyclic aliases mentioned before.  To prevent such situations
+                the search must maintain a common cache of entries that it has 
+                already returned.  The cache must be shared by all subordinate 
+                search cursors.  Alias dereferencing functionality implemented 
+                outside of the backend need not be pushed into the processor - 
+                it could reside in the nexus (a.k.a. the UnifiedBackend).  
+                Regardless of where it is located, if it does not reside within 
+                backends, it will have the same set of challanges to confront.  
+                These challanges will require recursive solutions.
+            </para>
+            
+            <para>
+                This approach is certainly not trivial however it does spare 
+                backends from having to manage aliases.  If aliases were 
+                managed by backends then they would have to manage them for all
+                protocol operations.  Each backend would have to apply its own
+                unique means to accomplish this depending on the nature of its 
+                backing store and hence its own design.  We explore these issues
+                with regard to the JDBM backend in the section to follow.
+            </para>
+            </section>
+            
+            
+            <section>
+            <title>Adding Alias Dereferencing Functionality To Backends</title>
+            <para>
+                The only other alternative design would be to delegate alias
+                dereferencing to backends.  This as mentioned before further 
+                complicates backend implementations making life even more 
+                difficult for backend implementors.  It also limits aliases,
+                preventing their use across DIBs.  Alias dereferencing design
+                and implementation would be highly specific to the nature of the
+                backend's backing store and would have to be implemented for 
+                each backend.  When analyzing the possibilities of this option 
+                we would have to focus on a specific backend, which makes the 
+                exercise valid for only that backend.  Nevertheless the 
+                exercise will lead to a better understanding of the hurdles to
+                overcome within backends in general.  For the exercise we chose
+                the default Jdbm based backend or modjdbm.  See the module 
+                documentation for more details on its operation.  We will 
+                presume the reader is already familiar with its design and its 
+                implementation.
+            </para>
+            
+            <para>
+                The modjdbm search algorithm factors scope directly into a
+                modified search filter's tree using a special type of node 
+                called a ScopeNode.  The search engine creates a new tree with a 
+                conjuction node at the root.  It attaches the ScopeNode 
+                underneath the root along with the filter expression tree 
+                generated from the user supplied search filter.  This is done 
+                before the optimization stage where the tree is evalutated by 
+                the search optimizer.  Introduction of the scope node before 
+                optimization considers scope while deciding the optimal search
+                route.  If the ScopeNode is chosen as the iteration loop a 
+                Cursor is created over entry ids which comply with search scope
+                requirements based on the search base.  For subtree scope the
+                ids of all descendants of the search base and the base entry 
+                itself are returned.  The cursor operates by performing a full
+                index scan on the DN index testing each entry to see if it is 
+                accepted by a descendant Assertion.  Entry DN's accepted by the 
+                assertion have their ids returned.  The optimizer rarely selects
+                the ScopeNode for iteration in subtree scope, due to an 
+                inefficient full index scan.  The search algorthim in most cases
+                opts to use the ScopeNode in assertion checks rather than in
+                iteration loops.  Whether the ScopeNode is used in iteration or
+                for assertion checks, the same Assertion is used to validate 
+                entries to return.  While iterating the candidate is accepted by
+                the assertion and in a lookup the candidate is also accepted or
+                rejected by the assertion.
+            </para>
+            
+            <para>
+                At the present moment the assertion used for the ScopeNode of
+                a subtree search leverages a single DN to determine if a 
+                candidate is a descendant.  In derefInSearching mode, all 
+                aliases and any indirect chains can be detected before the 
+                search begins.  The DNs of these aliases can be used to build
+                a composite disjunction Assertion for the ScopeNode used in 
+                iterations and lookups.  When used in iteration, the Cursor 
+                built for the ScopeNode equiped with the disjunction Assertion,
+                will return candidates under and at all the alias DNs.  In 
+                lookups, the disjunction Assertion will accept the ids of 
+                entries that are aliased as well as their descendants.
+            </para>
+            
+            <para>
+                The composite descendant Assertion built on multiple DNs can be 
+                spared the trouble of testing each candidate against all aliased
+                DNs.  Aliased entry DNs and the base DN can be consolidated 
+                depending on the relationships between the search base and the
+                aliased entries.  If an aliased entry is a descendant of the 
+                search base then it need not be added to the Assertion.  The 
+                subtree search on the base will eventually included the aliased
+                DN entry and its descendants.  Likewise the base DN need not
+                be added if an aliased entry refers to a parent of the DN.  The
+                subtree search from the aliased parent will eventually include
+                the base entry and its descendants.   This technique can be used
+                to consolidate M related DNs into one DN which is the top most 
+                parent of all descendant DNs.  DN consolidation makes simple 
+                cycles irrelavant to the search without dealing with redundant
+                returns or infinite loops.
+            </para>
+            
+            <para>
+                The one detail left out of all is the mechanism for detecting
+                the set of aliases dereferenced in the search and making their 
+                aliased entry DNs available to the search engine.  A special 
+                index can be built to track aliased names unlike the way normal 
+                indices work.  This special index would map the DN of the alias 
+                to the DN of the entry the alias refers to.  The search engine 
+                would start by scanning the keys of the index looking for DNs 
+                that are descendants of the search base.  The descendant DNs 
+                represent the DNs of all the aliases existing under the search
+                base.  The values of these DNs are appended to the set of DNs
+                that we need to add to the ScopeNode Assertion.  After the 
+                initial scan a similar scan is performed for every value added 
+                to the set until all values added have been checked to see if 
+                they have descendant aliases.  This way we capture all DNs
+                involved in alias chains.  In effect, alias dereferencing is 
+                being performed here for all aliases before the search begins.
+                Once all possible aliased entry DNs are resolved and accumulated
+                within a set, the consolidation process can begin.  The 
+                remaining DNs after consolidation are used to build the subtree
+                ScopeNode's Assertion.  Search then continues in the same 
+                fashion as it has before.  Surprisingly the solution is clean
+                and can be encapsulated outside of the search mechanism.
+            </para>
+            
+            <para>
+                The modjdbm design for alias dereferencing works out 
+                surprisingly well.  The process of dereferencing and the 
+                application of filter selection criteria are more seperable 
+                than we had first imagined.  The performance degradation due to
+                alias dereferencing is nominal.  The issues described within 
+                the "Future Considerations" section to follow do not hold with 
+                such a design - server side sorts can still be implemented 
+                without elaborate designs.  The only drawback is the inability 
+                to implement DIB crossing aliases.  Situations requiring such 
+                constructs can rely on the use of referrals instead.  These
+                surprising conclusions lead us to believe that alias handling
+                is best left upto the individual backend.
+            </para>
+            </section>
+            
+            <section>
+            <title>Furture Considerations</title>
+            <para>
+                Another consideration for choosing between these approaches is
+                the affect it will have on the ease in which other aspects of 
+                search will be designed and implemented.  Namely we are 
+                concerned with support for search operational modifiers like
+                control extentions.  An example of a popular search control 
+                extention is the server side sorting control.  This control
+                enables clients with a small memory foot print which cannot 
+                possibly hold the entire result set for sorting search results
+                by delegating the sort to the server.  The entries are returned 
+                sorted based on an attribute specified by the control.  
+            </para>
+            
+            <para>
+                The most efficient implementation for server side sorting would
+                leverage the sorted indicies of backends to have them return 
+                entries in sorted order.  The alternative of caching the result
+                set on the server after a search to sort the result before 
+                returning it would consume too much memory and processing time.
+                Backends could be asked to leverage their specific indexing 
+                scheme to return entries already sorted since indices usualy 
+                maintain their keys in sorted order.  It would be a waste to 
+                not take advantage of this, only to spend time and memory to
+                sort the results afterwords.
+            </para>
+            
+            <para>
+                The design where alias dereferencing is handled outside of 
+                backends through subordinate searches on aliased entries would 
+                fragment the sorted resultset returned by search cursors.  If a
+                parent search returning sorted entries stops at some alias entry
+                to return the sorted entries of a subordinate search then there
+                will be a discontinuity in sorting order.  The subordinate 
+                search would not return entries in order after the last entry
+                returned by the parent.  Likewise when the subordinate returns
+                its last entry, there is a discontinuity again in the sorting 
+                order when the parent search resumes where it left off.  Without
+                caching the entire set of entrys then iterating over them once 
+                again for the return to the client in sorted order, it would be
+                virtually impossible to manage server side entry sorting 
+                controls.  Doing so would unnecessarily consume both space and
+                time.
+            </para>
+            
+            <para>
+                ????
+                In the case of implementing alias dereferencing within the Jdbm 
+                based backend, modjdbm, the problem would still persist.
+            </para>
+            </section>
+        </section>
+    </section>
+    
+    <section>
+        <title>Alias Handling Implementation</title>
+        
+        <para>
+            We have decided to embed alias handling functionality into backends
+            enabling rapid alias handling without allowing the creation of DIB 
+            crossing aliases.  The following section elaborates on the details
+            of the implementation with respect to the default backend based on
+            JDBM.  The implementation of the JDBM backend is applicable to the
+            the implementation for the BerkeleyDB backend due to their extreme
+            similarity.  Other backend modules like the jdbc backend will be
+            very different.
+        </para>
+        
+        <section>
+        <title>The Implementation of Alias Dereferencing in Backends</title>
+        
+        <para>
+            The implementation shall separate alias handling into categories
+            based on scope and dereferencing modes.  These search parameters
+            are request specific.  The scope parameter is made available to the
+            backend through the search method as a method argument.  The alias
+            dereferencing mode is not and must be made available.  The lack of
+            access to the dereferencing mode parameter raises some questions
+            regarding the handling of request parameters.  There presently is
+            no localized access mechanism for request scope parameters.  In 
+            contrast, session scope parameter alteration and access is 
+            centralized and well defined within the ClientManager and its
+            helper interfaces.  Perhaps there needs to be a similar central
+            facility to access and alter mutable request parameters.  The answer
+            to this question is beyond the scope of this document and it needs
+            to be resolved before implementing any request parameter dependent
+            functionality such as alias dereferencing.
+        </para>
+        
+        </section>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/output-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/output-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,194 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: output-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:18:35  bearcej
+Fixed figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    output-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:32  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:21  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.2  2003/03/09 01:33:58  akarasulu
+Completed OuputModule documentation and refactored annon inner class for
+handler into named inner class.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The OutputModule implements the OutputManager service interface used
+            to transmit LDAPv3 ASN.1 BER encoded message responses to clients on
+            a server OutputStream.  The module is implemented as a stage which
+            asynchronously processes OutputEvents carrying the message to 
+            transmit as well as the client key used to identify the client 
+            stream.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+            The OutputManager interface extends two subinterfaces: 
+            OutputListener and ClientManagerSlave.  The OutputListener interface
+            gives the OutputManager its event processing character by defining
+            a single method called writeResponse to process its OutputEvent
+            argument.  The OutputModule which implements OuputManager, is 
+            implemented as a OutputEvent processing stage.  The OutputEvents are
+            delivered through the OutputListener.writeResponse() method which
+            returns immediately after enqueueing the event onto the stage event
+            queue.
+        </para>
+        
+        <para>
+            The ClientManagerSlave interface is extended by the OutputManager to
+            prevent containers of this module from detecting a cyclic dependency
+            between the ClientManager and eventually this module.  This 
+            interface essentially defines a method that is called by the 
+            ClientManager on initialization to set the handle of these slave on
+            the ClientManager service.  This avoids the use of the conventional
+            service life-cycle method to initialize the handle on the 
+            ClientManager.  If the handle were gotten by the ServiceManager fed
+            into the service method, the cyclic dependency would be caught and
+            the server would not start.  Hence this module is a slave to the 
+            ClientManager since it must have a member handle initialized by it.
+        </para>
+        
+        <para>
+            The OutputManager interface defines three other service methods.  
+            These are: write(), register() and unregister().  The write() method
+            is a special synchronous flush of a response message which bypasses
+            the asynchronous stage processing of the OutputEvent.  It directly
+            requires the client key and the message PDU in the form of an 
+            InputStream with both provided as arguments.  The synchronous write
+            method is a work around to bypass staged processing to facilitate
+            the synchronous delivery of search responses.  The search request 
+            process calls this method to maintain the order of responses in a
+            train of search entry response message envelopes.  The other two 
+            methods are defined to enable the registration and unregistration
+            of client's that must have response messages delivered to them.  
+            When client's connect to the server, the ListenerModule adds the
+            client to the ClientManager.  The ClientManager then on behalf of
+            the listener registers the client's InputStream with the 
+            InputManager and registers the client's OutputStream with the 
+            OutputManager.  This enables the stage pipling to go full circle by
+            recieving input requests, processing then, and returning the 
+            responses to the client.
+        </para>
+        
+        <figure>
+            <title>OutputModule's OutputEventHandler Sequence Diagram</title>
+            <graphic fileref="../images/OutputEventHandlerHandleEvent.gif"/>
+        </figure>
+
+        <para>
+            This stage is extremely simple.  Like other stages its driver 
+            dequeues an incoming event, and creates an annonymous inner Runnable
+            to drive the call to the stage event handler's handleEvent method in
+            the execution context of a stage worker thread.  The OutputEvent is
+            provided as the sole argument to the handleEvent() method on the 
+            EventHandler.  The gist of the work done within the write() method 
+            of the module which is called by the handler.  Essentially the 
+            handler just extracts the client key and the InputStream to the 
+            response buffer from the OutputEvent argument.  It then feeds them 
+            both into the synchronous write() method as arguments.  The same 
+            write() method used by the search request processor to synchronously
+            deliver response messages is used to asynchronously deliver messages
+            when driven by a worker thread.  The trivial eventHandler method is 
+            depicted in the sequence diagram above.
+        </para>
+        
+        <figure>
+            <title>OutputModule's write() Method Sequence Diagram</title>
+            <graphic fileref="../images/OutputModuleWrite.gif"/>
+        </figure>
+        
+        <para>
+            As can be seen from the sequence diagram above depicting the flow of
+            the write() method, the client key is used to lookup the OuputStream
+            of the client.  Then after acquiring a lock on the output lock 
+            object, a while loop is entered which reads from the InputStream 
+            argument.  The InputStream reads from the encoded response message
+            buffer constructed by the upstream encoder stage.  Once the buffer
+            has been consumed or the client key expires the loop terminates.  
+            For all practical purposes it can now be concluded that the reponse
+            message has been delivered to the client.  notifyAll() is then 
+            called to awaken threads blocked waiting for the OutputStream of the
+            client. 
+        </para>
+        
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            This module is pretty solid.  
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            None so far.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/protocol-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/protocol-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,979 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+	"http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+	<title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: akarasulu $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.7 $</revnumber>
+                <date>$Date: 2003/08/22 21:15:54 $</date>
+                <revdescription>
+                    <para>
+$Log: protocol-module.xml,v $
+Revision 1.7  2003/08/22 21:15:54  akarasulu
+Merged changes made in the USING_PROVIDER_FRAMEWORK branch of the
+server.  I don't suspect she will be working well at this point.  Lots
+of overhauling required now.
+
+Revision 1.3.2.2  2003/05/17 16:58:52  akarasulu
+started an addendum section for refactorings which will be used to refactor
+this document to synch it up with the code changes currently under way w/i
+the USING_PROVIDER_FRAMEWORK brach.
+
+Revision 1.3.2.1  2003/05/05 17:28:54  akarasulu
+Moving towards the request handler flywieght pattern away from the
+per request dedicated processor based design of the protocol engine.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.4  2003/03/15 22:30:30  bearcej
+Fix last figure href.
+
+Revision 1.1.2.3  2003/03/15 17:16:47  bearcej
+Fixed figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+	protocol-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:32  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:21  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.6  2003/03/09 00:36:54  akarasulu
+Finished encoder docs and refactored inner annonymous handler to be a
+named inner class.
+
+Revision 1.1.2.5  2003/03/08 23:38:42  akarasulu
+Completed protocol engine documentation along with subsections for the
+various protocol request processors used.
+
+Revision 1.1.2.4  2003/03/07 20:50:47  akarasulu
+*** empty log message ***
+
+Revision 1.1.2.3  2003/03/07 20:49:33  akarasulu
+Adding Bind docs
+
+Revision 1.1.2.2  2003/03/06 23:11:26  akarasulu
+Proof read decoder module and added some content to protocol module docs.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+	<abstract>
+		<para>
+			The ProtocolModule is the heart of the server.  It contains the
+			logic required to service each LDAPv3 protocol request and if need
+			be construct one or more response PDUs.  The module implements the
+			RequestListener interface to have RequestEvents delivered for 
+			processing.  It is implemented as a stage and consequently can 
+			process several requests in parallel.
+		</para>
+	</abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add sequence diagrams.
+            </para></listitem>
+            <listitem><para>
+                Add link to relavent rfc 2251 sections.
+            </para></listitem>
+            <listitem><para>
+                Add diagrams showing the composition of both request and 
+                where relavent response envelopes.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Background</title>
+        
+        <para>
+            The decoding stage of the server delivers decoded Requests to the 
+            protocol stage using RequestEvents.  The request events carry the
+            Request and the ClientKey for the client submitting the Request.  It
+            is the responsibility of the protocol stage to service each request
+            using the resources available.
+        </para>
+            
+        <para>
+            Based on the message type, the manner in which Requests are serviced
+            differs.  The majority of Request messages produce a single Response
+            as a reply.  AbandonRequest, and UnbindRequests produce no Response 
+            at all.  Conversely, in the course of servicing a SearchRequest many
+            Responses of various message types may be generated in reply.  
+            According to RFC 2251 a SearchRequest must reply with a 
+            SearchResponseDone to mark the end of the reply.  Before 
+            transmission of the SearchResponseDone, zero or more (in any order)
+            SearchResponseEntry, SearchResponseReference and ExtendedResponses
+            may be returned to the client.  These vastly differing modes of 
+            Request handling makes it difficult to devise a generalize mechanism
+            to process all requests.  The best approach would be to devise a 
+            processing scheme for each category of request.
+        </para>
+        
+        <para>
+            The protocol imposes no requirement enforcing ordered response 
+            delivery between request messages.  The message sequence identifier
+            is used to prevent the protocol from having to impose such 
+            requirements.  Hence the response to request 3 may be returned 
+            before the response to request 1.  The server's seda architecture 
+            takes advantage of this be enabling the asynchonous staged delivery
+            of responses back to a client.  Whenever a response to a request is
+            composes it is returned back to the client asynchronously without 
+            concern for the order of delivery.  The multiresponse nature of the
+            search request does however impose a response delivery order within
+            a message request.  All Responses delivered in reply to a 
+            SearchRequest have the same message sequence identifier.  This way 
+            they are all associated with the same SearchRequest.  Our only 
+            problem is the need to return some search responses before others 
+            in a asynchronous response delivery environment.
+        </para>
+        
+        <para>
+            The SearchRequest presents many design hurdles to overcome.  The 
+            server must synchronize the delivery of search responses within a 
+            SearchRequest.  Searches using the sort control extention cannot 
+            return sorted entries without synchronous delivery to maintain 
+            sorting order.  Furthurmore we must ensure the last response sent to
+            be the SearchResponseDone message.
+        </para>
+    </section>
+    
+    
+    <section>
+        <title>Architecture</title>
+        
+        <para>
+			As a stage the work of processing RequestEvents is delegated to the
+			stage worker threads.  The worker threads as in other stages drive
+			the synchronous call to the stage's event handler.  The stage event
+			handler accepts event's and specifically with regard to this module
+			it requires events to be RequestEvents.  So far these aspects to the
+			module's architecture are really based on the architecture of a 
+			stage.
+        </para>
+        
+        <para>
+            The use of the new Message Framework encapsulates protocol request
+            parameters and other message parameters within a Request object.
+            The Request object can be used to store request processing state 
+            rather than embedding state tracking into some kind of request 
+            processor object for each request.  The FlyWeight design pattern 
+            can be used to have a specific processor instance service all 
+            requests of a particular request message type.  Previously before 
+            the Message Framework, a specific processor would be instantiated to 
+            track and process each request.  Once processing was complete the
+            processor memory would be reclaimed.  Each incomming request would 
+            instantiate a processor.  The processor itself served to encapsulate
+            request protocol parameters like a request bean to prevent other 
+            parts of the system from having to deal with ASN.1 compiler stubs.
+            Now with a clean explicit API to represent messages independent of 
+            the ASN.1 stub compiler and BER library used we can expose a Request
+            bean rather than a processor wrapping a stub class.
+        </para>
+            
+        <para>
+			Still the specific processing of each type of protocol requests is 
+            best handled using separate request processor implementations.  For
+            now we will just call them handlers.  They really are specific 
+            request message type handlers with the new Message framework.  A 
+            handler unlike a processor, can be used to safely handle several
+            requests concurrently whereas a processor is dedicated to an 
+            individual request.  We can easily find the request handler for a
+            request based on the message type enumeration.  A RequestHandler 
+            interface is designed to standardize handler operations.  The 
+            stage's handler selects the specific request handler for the 
+            respective request off of a switch on the protocol message type.  
+            After assigning the Request to a handler, generic handling interface
+            methods can be used to manage the process without regard to type 
+            specifics.
+        </para>
+        
+        <para>
+			The work of a request handler is performed in a simple handleRequest 
+            method that returns a potentially null handle on a Response.  The 
+            stage's event handler simply calls this method on the processor.  If
+            the request requires a response the response is handed off to the 
+            next downstream stage (the decoder) in the form of a ResponseEvent.  
+            The response if one is to be returned is the LDAPMessage object 
+            returned by the process method.
+        </para>
+		
+		<para>
+			The use of processors to handle requests based on type is a form of
+			the Reactor design patten and has several benefits.  First and 
+			foremost it separates the handling of each request out into separate
+			classes thereby minimizing complexity.  Second it provides a place 
+			where request specific parameters can be managed, like the request 
+			PDU envelope (an LDAPMessage instance).  Finally a common super 
+			interface standardizes request event handling by manipulating each
+			request processor implementation through the methods of this common 
+			interface.
+		</para>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+			The best approach to describing the implementation is to generally 
+			describe the event handling from an enqueue onto this stage's queue 
+			on upto the death of a stage worker thread without dealing with the
+			specifics of each processor.  The specifics of each processor's 
+			implentation is handled in separate request specific sections.
+        </para>
+        
+        <para>
+			As noted, this module is implemented as a stage to enable parallel
+			processing of multiple request events.  Event processing is handled
+			asynchronously by stage worker threads.  The RequestListener's
+			requestReceived method implementation simply enqueues the 
+			RequestEvent argument onto the stage event queue.  Hence, the 
+			requestReceived method called by an upstream decoder stage worker 
+			thread returns immediately.
+        </para>
+        
+        <para>
+			Once the RequestEvent is enqueued, the stage dedicates a worker to 
+			drive an instance of an annonymous Runnable class.  The Runnable's 
+			run method, as in all stages, calls the stage's EventHandler passing
+			it the RequestEvent.  A named inner class called a 
+			RequestEventHandler is defined and an instance of it is instantiated 
+			within the module's default constructor.  This is the EventHandler 
+			implementation used for this stage.  The RequestEventHandler's 
+			handleEvent method is called by the annonymous Runnable's run 
+			method.
+        </para>
+		
+		<figure>
+            <title>ProtocolModule's RequestEventHandler Sequence Diagram</title>
+	    <mediaobject><imageobject>
+            <imagedata fileref="images/RequestEventHandlerHandleEvent.gif"/>
+	    </imageobject></mediaobject>
+		</figure>
+		
+		<para>
+			The primary function of the eventHandler implementation is to 
+			instantiate the correct RequestProcessor matching the request and 
+			call the RequestProcessor.process() method.  Initially the handler
+			checks that the event is an instance of RequestEvent, and accesses
+			the parameter's of the request packaged into the RequestEvent.  
+			These include the request envelope as an LDAPMessage, the ClientKey,
+			and the message type value used in the switch to follow.  The switch
+			is on the message type and it is used to instantiate the appropriate
+			RequestProcessor.  Once the RequestProcessor is set the current 
+			thread of execution is bound to the processor within a ThreadLocal
+			to access request parameters during the coarse of processing the 
+			request without passing around several variables.  The service and
+			initialize life-cycle methods of the RequestProcessor are called to 
+			prepare it for the process invokation.  The call to the process 
+			method returns a handle on a response if one exists.  If a response
+			is to be returned by the processor it is packaged into a 
+			ResponseEvent and delivered to the next downstream stage, the 
+			encoder.  Whether or not a response is generated the executing 
+			thread is disassociated with the RequestProcessor after the call
+			to process.  After this last step the handler returns.  The entire
+			sequence is depicted in the sequence diagram above.  The specifics
+			of each RequestProcessor's process method is discussed in details
+			within the sections to follow.
+		</para>
+
+		<section>
+        	<title>AbandonRequestProcessor</title>
+			
+			<para>
+				The purpose of the AbandonRequestProcessor is to implement the 
+				abandon protocol operation.  This processor is not yet 
+                implemented.  According to the protocol this operation does not
+                produce as response.
+			</para>
+		</section>
+
+		<section>
+        	<title>AddRequestProcessor</title>
+			
+			<para>
+				The purpose of the AddRequestProcessor is to implement the add 
+                protocol operation.  This operation adds a single new entry at 
+                the base of an existing entry.  According to the protocol this 
+                operation must produce a response indicating success or failure.
+			</para>
+            
+            <para>
+                The processor is created by passing the client's key and the 
+                request envelope to the constructor.  On initialization the 
+                response envelope is allocated and populated minimally with the
+                message sequence id and an empty AddResponse object.  The 
+                service method initializes handles on dependent modules: the
+                UnifiedBackend and the EventManager.
+            </para>
+            
+			<figure>
+				<title>
+					AddRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/AddRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+            <para>
+                Before wasting time and resources by investigating the contents
+                of the request envelope the processors process() method checks 
+                to see if the entry to be added already exists by calling the 
+                hasEntry method of the UnifiedBackend.  The protocol request 
+                contains the set of attribute identifiers and their single or 
+                multiple values.  These values are extracted from the request 
+                envelope using the stubs generated by the Snacc4J compiler.  
+                These attributes and values are added to an empty LdapEntry 
+                returned by the UnifiedBackend.  The LdapEntry implementation is 
+                constructed by the AtomicBackend associated with the naming 
+                context under which the name of the entry to be added exists.
+                The UnifiedBackend automatically routes these kinds of calls to
+                the naming context's AtomicBackend.  Once populated a pre-event
+                announcement via the fireBefore() method of the EventManager is
+                made.  The create method on the UnifiedBackend is called to 
+                create (add) this new attribute.  Immediately there after 
+                another post-addition protocol event is fired via the 
+                EventManager's fireAfter method.  See the sequence diagram for
+                high level view of the add operation's success pathway.
+            </para>
+		</section>
+        
+		<section>
+        	<title>BindRequestProcessor</title>
+			
+			<para>
+				The purpose of the BindRequestProcessor is to implement the 
+				bind protocol operation.  The processor depends on the 
+				EventManager, UnifiedBackend and AuthenticationManager services.
+                The bind operation generates a bind response no matter what the
+                results of the bind operation.
+			</para>
+			
+			<para>
+                An instance of the bind processor is created by passing the 
+                ClientKey, a handle to the ClientManager service and the 
+				LDAPMessage request as arguments to the constructor.  The call 
+                to initialize allocates a response LDAPMessage to the bind 
+                request which is an empty envelope.  Some preparations are made
+				to the request envelope like adding the message sequence id, and
+				initializing the BindResponse object.  The service method is
+				next in line and is called by the handler after calling 
+				initialize.  The service method is used to pass service handles 
+				to the processor.  The handle to the AuthorizationManager, the
+				UnifiedBackend and the EventManager are acquired here.
+			</para>
+			
+			<figure>
+				<title>
+					BindRequest Processor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/BindRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+				After all life-cycle methods are invoked the process method is 
+				called.  The highlevel sequence of events within the process() 
+                method are shown in the sequence diagram above.  Currently the 
+                only available authentication method is simple.  SASL based 
+                authentication is not available.  Therefore the diagram 
+                represents the steps towards successfully authenticating a user 
+                via the simple method pathway.  It does not show error handling 
+                functionality within the processor.  SASL authentication 
+                attempts and various exceptions which may occur result in the
+                construction of an alternative LDAPMessage response object.  In 
+                these cases the error or unavailability of an operation result 
+                in a response returning the respective LDAP error code along 
+                with a descriptive message regarding the error.
+			</para>
+            
+            <para>
+                The normal operational pathway for the processor first results
+                in the construction of a bind protocol event which is delivered
+                to protocol event listeners via the EventManager service.  This
+                pre-event announcement is depicted in call 1.1 of the diagram.
+                The processor then invokes the loginSimple method of the 
+                AuthenticationManager which either results in a LoginException 
+                or returned a valid Pricipal object.  Presuming the correct
+                credentials were supplied, the processor then creates the 
+                client's session by calling create on the ClientManager service
+                interface.  Thereafter the processor fires a post-event 
+                announcement using the fireAfter method on the EventManager and
+                returns.
+            </para>
+            
+            <para>
+                Exceptional conditions at any point result in the return of an
+                envelope packaged with the LDAP error code and a descriptive
+                message.
+            </para>
+		</section>
+
+        <section>
+        	<title>CompareRequestProcessor</title>
+			
+			<para>
+				The purpose of the CompareRequestProcessor is to implement the 
+				compare protocol operation.  The processor depends on the 
+				EventManager, and the UnifiedBackend services.  The purpose of
+                the operation is to evaluate an attribute assertion on an entry 
+                specified by DN.  The compare operation generates a compare 
+                response no matter whether the operation succeeds, fails or
+                generates an exception during processing.
+			</para>
+			
+			<figure>
+				<title>
+					CompareRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/CompareRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The processor is instantiated by passing the client key and the
+                request message envelope as arguments to the constructor.  On
+                initialization the response message envelope is allocated and
+                populated with the message sequence id and an empty 
+                CompareResponse.  The handles on the dependent UnifiedBackend 
+                and EventManager services are acquired after initialization with
+                a call to the processor's service method.
+			</para>
+            
+            <para>
+                Once the process method is called the processor attempts to 
+                resusitate the LdapEntry to be tested using the attribute value
+                assertion contained in the compare request envelope.  Next the
+                entries attributes are tested to see if they comply with the
+                assertion.  The results of the test are then packaged into the
+                compare response returned within the LDAPMessage envelope.  
+                Before returning the response the process method announces 
+                operation completion via the EventManager's fireAfter method.
+            </para>
+
+            <para>
+                Exceptional conditions at any point result in the return of an
+                envelope packaged with the LDAP error code and a descriptive
+                message.
+            </para>
+        </section>
+        
+        <section>
+        	<title>DelRequestProcessor</title>
+			
+			<para>
+				The purpose of the DelRequestProcessor is to implement the 
+				delete protocol operation.  The processor depends on the 
+				EventManager, and the UnifiedBackend services.  The purpose of
+                the operation is to remove a single entry specified by DN.  The
+                operation according to the LDAPv3 protocol will fail if the
+                target entry has children.  The delete operation generates a 
+                response no matter whether the operation succeeds, fails or
+                generates an exception during processing.
+			</para>
+			
+			<figure>
+				<title>
+					DelRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/DelRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The processor is instantiated by the protocol engines stage
+                event handle by a call to the constructor passing in the client
+                key and the request message envelope.  On initialization the
+                response message envelope is allocated and populated with the
+                message sequence id and an empty delete response object.  
+                Handles to the dependent UnifiedBackend and EventManager 
+                services are initialized on the call to the service life-cycle
+                method before the process method is called.
+			</para>
+            
+            <para>
+                The process method first resusitates the target entry to delete
+                from the UnifiedBackend with a read call that returns a handle
+                on an LdapEntry.  This confirms the existance of the entry and
+                facilitates the call to delete() which requires an LdapEntry as
+                the argument.  Then a pre-event announcement is made via a call
+                to the fireBefore method of the EventManager.  The call to the
+                delete method is made using the returned LdapEntry.  Finally
+                before returning the response envelope confirming the deletion,
+                a post protocol operation is announced via the fireAfter method
+                of the EventManager.
+            </para>
+            
+            <para>
+                Exceptional conditions at any point result in the return of an
+                envelope packaged with the LDAP error code and a descriptive
+                message.
+            </para>
+		</section>
+        
+        <section>
+        	<title>ExtendedRequestProcessor</title>
+			
+			<para>
+				The purpose of the ExtendedRequestProcessor is to implement the 
+				extended protocol operation.  The processor depends on the 
+				EventManager, and the UnifiedBackend services.  The purpose of
+                the operation is to enable protocol compliant operation 
+                extentions.  The request contains an OID and a binary payload
+                holding the parameters required in an operation specific format.
+                The operation is simply a pass through to execute some type of
+                application specific or server specific operation.  The extended
+                operation generates a response no matter whether the operation 
+                succeeds, fails or generates an exception during processing.
+			</para>
+			
+			<figure>
+				<title>
+					ExtendedRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+                		<imagedata fileref="images/ExtendedRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The processor is instantiated by passing the client key, the
+                request message envelope and a handler map to the constructor.
+                The handler map contains a map of OID Strings to ExtReqHandler
+                instances.  These handlers are simple implementations of 
+                functions with assigned OIDs.  They take the payload as a byte 
+                array argument which is extracted from the extended request 
+                envelope and return a byte array.  The returned byte array 
+                represents the extended response payload which is packaged into
+                the response envelope returned by the processor's process 
+                method.  These extended request handlers and the OID to handler
+                map are created by the protocol engine during the module's 
+                configuration life-cycle phase.
+			</para>
+            
+            <para>
+                By providing the extended request handler map in the constructor
+                the processor can invoke the appropriate handler on the request
+                payload and hence respond to the request using the resultant 
+                response payload.  Following instantiation the processor is 
+                initialized creating the empty extended request message envelope
+                populated with the message sequence id and an empty 
+                ExtendedResponse object.  Then before the process method is 
+                called the service method is called to acquire handles on the 
+                dependent EventManager service.  It is very likely that other
+                service dependencies will exist however since we have not 
+                implemented any of these extended request handlers we know of 
+                none for now.  Eventually it will be necessary to enable 
+                extended request handlers with handles to other dependent 
+                modules.  This will require a change to the extended request 
+                handler or to its implementation to have it implement the 
+                Serviceable interface.  Handles to dependent services within 
+                the server to do the work of processing the extended request
+                can be obtained through this standard Avalon life-cycle method.
+            </para>
+            
+            <para>
+                The process method immediately announces the arrival of an 
+                extended request by calling the fireBefore method of the 
+                EventManager service.  It then calls the handle method of the
+                OID specific handler using the extracted payload of the request
+                envelope.  Then before the resultant payload is packaged into
+                the response envelope and returned the fireAfter method of the
+                EventManager is called.
+            </para>
+            
+            <para>
+                Exceptional conditions at any point result in the return of an
+                envelope packaged with the LDAP error code and a descriptive
+                message.
+            </para>
+		</section>
+        
+        <section>
+        	<title>ModifyDNRequestProcessor</title>
+			
+			<para>
+				The purpose of the ModifyDNRequestProcessor is to implement the 
+				modify DN protocol operation.  The processor depends on the 
+				EventManager, and the UnifiedBackend services.  The purpose of
+                the operation is to change the name of an entry and consequently
+                the DN of every descendant entry.  The modify DN operation can
+                optionally change the Rdn attribute used by the target entry.  
+                The operation generates a response no matter whether it 
+                succeeds, fails or generates an exception during processing.
+			</para>
+			
+			<figure>
+				<title>
+					ModifyDNRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+                		<imagedata fileref="images/ModifyDNRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The call to the constructor with a client key and the request
+                message envelope is made by the protocol engine stage's event
+                handler.  Once instantiated the call initialize again by the
+                event handler allocates a response message envelope populated
+                with the message sequence id and an empty ModifyDNResponse
+                object.  The call to the service method next by the handler 
+                initializes processor member variables referring to the 
+                dependent services.
+			</para>
+            
+            <para>
+                The process method of the processor first checks to see if the
+                target entry whose DN is to be modified exists.  If the entry
+                exists a pre modify DN announcement is made via the fireBefore
+                method of the EventManager service.  Next the modifyRdn method 
+                is called on the UnifiedBackend service and then a call is made
+                to fireAfter to announce the completion of the operation on the
+                EventManager service.  The results of the operation are returned
+                after being packaged into the response envelope.
+            </para>
+            
+            <para>
+                Exceptional conditions at any point result in the return of an
+                envelope packaged with the LDAP error code and a descriptive
+                message.
+            </para>
+		</section>
+        
+        <section>
+        	<title>ModifyRequestProcessor</title>
+			
+			<para>
+				The purpose of the ModifyRequestProcessor is to implement the 
+				modify protocol operation.  The processor depends on the 
+				EventManager, and the UnifiedBackend services.  The purpose of
+                the operation is to change, remove or add a set of attribute 
+                value pairs to an entry specified by DN.  The operation 
+                generates a response no matter whether it succeeds, fails or 
+                generates an exception during processing.
+			</para>
+			
+			<figure>
+				<title>
+					ModifyRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/ModifyRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The processor is instantiate via a standard constructor call 
+                taking the client key and the request message envelope as its
+                arguments.  The initialize method call made by the protocol 
+                engine stage event handler allocates a response message envelope
+                populated with the message sequence id and an empty 
+                ModifyResponse.  Finally before assigning a worker to process
+                the request the service method is called by the handler to 
+                initialize handles on the dependent services required by this
+                processor.
+			</para>
+            
+            <para>
+                Once the worker thread calls process, the target entry is 
+                resusitated from the owning context via a call to the 
+                UnifiedBackend's read method.  Next the resusitated entries
+                are modified according to the changes described by the modify
+                request envelope.  At this point before calling update the 
+                pre modify operation must be fired, yet it seems to have been
+                overlooked.  It needs to be fired.  Next a the call to update 
+                on the UnifiedBackend is made to effect the changes made to the
+                target entry.  Finally before returning the response message 
+                envelope the processor needs to call the fireAfter method on the
+                EventManager service yet again this seems to have been 
+                overlooked.
+            </para>
+		</section>
+        
+        <section>
+        	<title>SearchRequestProcessor</title>
+			
+			<para>
+				The purpose of the SearchRequestProcessor is to implement the 
+				search protocol operation and it is by far the most complex of
+                all the protocol operations.  The processor depends on the 
+				EventManager, the UnifiedBackend, the Encoder and OutputManager 
+                services.  The purpose of the operation is to search the 
+                directory returning zero or more entries or references to 
+                entries while appling search controls to moderate the operation.  
+                The operation generates a response no matter whether it 
+                succeeds, fails or generates an exception during processing.
+			</para>
+            
+            <para>
+                The search operation as mentioned before is the most complex. As
+                a consequence the processor implementation for it is complex as
+                well.  The search operation can return one or more responses to 
+                the client or zero or more entry or referrals.  The search 
+                operation uses different responses for each entry returned, from
+                each referral to a remote entry.  Referral response message 
+                envelopes hence have the url of the entry whereas entry response
+                message envelopes contain the attributes of the entry.  Not to
+                mention these response types, at the end of the operation once 
+                the search has completed a search done response message must be
+                delivered to the client.  The search done response message 
+                envelope has yet another makeup.
+            </para>
+            
+            <para>
+                While managing the delivery, the search processor must take 
+                search controls into account to moderate the operation.  For
+                the time being controls are not fully implemented.  As a 
+                consequence of the need to sychronize the ordered receipt of 
+                messages the search processor must use synchronous message 
+                delivery methods on the Encoder and the OutputModule for all
+                response messages except the final search done response.  These
+                factors complicate the operation of the processor.
+            </para>
+            
+			<figure>
+				<title>
+					SearchRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/SearchRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                The processor is instantiated via a call to its constructor 
+                using the client key and the request message envelope as 
+                parameters.  The initialize life-cycle method does nothing since
+                the response message processing can be handled usind more than
+                one type of response unlike other protocol operations.
+			</para>
+            
+            <para>
+                Since the processor directly manages and drives the synchronous
+                delivery of all responses except for the final search done 
+                response it must communicate with the Encoder and the 
+                OutputModule directly without relying on staged event processing
+                pathways within the server.  This is why the processor must 
+                initialize a handle on both the Encoder and OutputManager 
+                services as well as the EventManager and UnifiedBackend services
+                during the service life-cycle method.
+            </para>
+			
+            <para>
+                Once processing begins the processor extracts the base DN, 
+                search controls and filter information for the search from the
+                request message envelope.  A pre search event is then fired from
+                the EventManager service's fireBefore method.  Now the processor
+                is ready to call the search method on the UnifiedBackend 
+                service.  The search simply returns a Cursor which requires a
+                loop to extract the candidate entries to return.  Within the 
+                loop synchronous calls are made to special method interfaces 
+                for synchronous processing on the Encoder and OutputManager 
+                services.  Once all the entry and referal response messages have
+                been delivered synchronously to the client, the last search done
+                response message envelope is constructed and returned to the
+                caller.  This last response message envelope is delivered 
+                asynchronously to the client using the standard staged pathways
+                of the server.
+            </para>
+		</section>
+        
+        <section>
+        	<title>UnBindRequestProcessor</title>
+			
+			<para>
+				The purpose of the UnBindRequestProcessor is to implement the 
+				unbind protocol operation.  The processor depends on the 
+				CllientManager only and the handle is passed in the constructor.  
+                The purpose of the operation is to drop a client and destroy 
+                their session and associated resources.  The operation does not
+                generate a response - the client socket drop can be considered
+                the response however clients usually close their connections
+                just after sending this request.
+			</para>
+			
+			<figure>
+				<title>
+					UnBindRequestProcessor's process() Sequence Diagram
+				</title>
+				<mediaobject><imageobject>
+				<imagedata fileref="images/UnBindRequestProcessorProcess.gif"/>
+				</imageobject></mediaobject>
+			</figure>
+		
+			<para>
+                This very simple processor is instantiated via a call to its 
+                constructor requiring as arguments a handle to the ClientManager
+                service, a client key, and the request message envelope.  Both
+                the initialize and service life-cycle methods do nothing at all
+                with empty method bodies.
+			</para>
+            
+            <para>
+                The process method should announce the unbind protocol operation
+                before and after droping the client connection yet this is not
+                the case.  It merely drops the connection through a call to the
+                drop method of the client manager.  It returns null indicating
+                that no response is to be returned to the client.
+            </para>
+		</section>
+        
+    </section>
+    
+    
+    
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+			We need to revaluate whether or not we are using ThreadLocals 
+			correctly.
+        </para>
+
+        <para>
+			We need to cleanup the processor code perhaps wrapping access to
+			the Snacc4J generated classes.  Later when and if we use other ASN.1
+			stubs only the stub wrappers will have to change.
+        </para>
+
+        <para>
+			We may want to look at using the JNDI provider to access backends
+			rather than going directly through the nexus module.  The JNDI 
+			provider may be able to transparently manage and encapsulate the 
+			referal management code on behalf of the protocol engine.
+        </para>
+
+        <para>
+			We need to implement the AbandonRequestProcessor for the Abandon
+			request type.  This will require access to the client's session 
+			which may have to hold the executing processor's which will need to
+			be stopped.  In this case the RequestProcessor implementations will
+			need to have some form of termination variable that can be checked
+			every now and then by the executing thread.  These are problems best
+			solved through aspect oriented techniques.
+        </para>
+		
+		<para>
+			Based on the decisions made on using the JNDI provider inside the
+			processors to access backends we may need to put protocol event 
+			firing hooks into all processors to fire their respective protocol
+			event.
+		</para>
+
+        <para>
+            Need to make all processors consistant in the way they handle
+            reporting errors.  Namely I would like to see stack traces returned
+            to the client only if debugging is enabled.
+        </para>
+        
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Pre and Post modify protocol events are not fired by the 
+            ModifyRequestProcessor.
+        </para>
+        
+        <para>
+            Pre and Post unbind protocol events are not fired by the 
+            UnBindRequestProcessor.
+        </para>
+    </section>
+    
+    <section>
+        <title>Adendum</title>
+        
+        <para>
+            In the process of refactoring the protocol module and its processors
+            using message beans from the Common Message API (CMA) we started to
+            use the JNDI provider instead of directly interfacing with the 
+            UnifiedBackend.
+        </para>
+
+        <para>
+            There are some issues that arise when using the JNDI provider 
+            specifically in the area of translating Exceptions back into 
+            LDAPv3 result codes.  Some JNDI exceptions are used to represent
+            multiple result codes.  Result code to JNDI exception mappings are
+            published <ulink url=
+            "http://java.sun.com/products/jndi/tutorial/ldap/models/exceptions.html">
+            here</ulink> on the SUN Java site. There is no way for the protocol 
+            module to tell which result code to use when it encounters an 
+            exception that can map to more than one result code.  Using the 
+            JNDI provider hence results in a loss of resolution.  For example 
+            the OperationNotSupportedException can represent result codes 12 and
+            53 for unavailable critical extensions and an unwillingness to 
+            perform an operation respectively.  Hence when the protocol engine 
+            catches a OperationNotSupportedException on calls to the JNDI 
+            interfaces there is no way for it to determine the cause of the 
+            exception.  The protocol engine cannot associate the error with a 
+            Control or Extended opertation that is unsupported with a situation
+            that the server implementation specifically does not support like
+            the deletion of a suffix entry.  We have solved this problem for the
+            time being by embedding the result code enumeration value into the 
+            exception message.  Since the result code can range from 1 to 80 
+            there are at most 2 digits required to represent it within the 
+            message.  We use a 4 character prefix which holds the 2 digit result
+            code value surrounded by '[' ']' brackets.  When handling exceptions 
+            this 4 character prefix is detected if present and the result code
+            is extracted from the exception message.  At the present time this 
+            is a kludgy solution yet it saves us the hastle of extending JNDI 
+            exceptions only to add a result code property to it.
+        </para>
+        
+        <para>
+            With the result code situation above we could have taken another
+            approach.  The code throwing the exception could store the response
+            code directly in the response by accessing the response being 
+            processed.  This will spread the code around involved with 
+            manipulating or building the response rather than centralizing it.  
+            These approaches need to be considered thoroughly before commiting 
+            to any one of them.  Regardless of the approach the region 
+            generating the exception needs to be aware of the result code to 
+            associate with the exception.  Some of this code is within the JNDI
+            provider, some within the nexus and some deep down within the 
+            backends.  The only difference with giving access to the response 
+            is that we enable its alteration within other modules.  There is no 
+            way to manadate every peice of code throwing an exception to use 
+            whatever mechanism we choose.  It would be nice to be able to have a
+            means to enforce it but this is not easy.  Nevertheless before 
+            sending the response to the encoder the handlers of the protocol
+            module need to detect whether or not the result code was set by the
+            exception handling code in the ldap result of a response.  If it did
+            not some default result code would need to be used instead.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/request-session-scopes.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/request-session-scopes.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,273 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Request and Session Scope Management</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.2 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: request-session-scopes.xml,v $
+Revision 1.2  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.1  2003/04/04 01:40:16  akarasulu
+Added more to search operation document yet temporarily suspended it to
+start working on request scope management design which all operations will
+eventually depend upon.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The management of session and request state requires distinct
+            structures within the server design.  Read only and mutable 
+            parameters within either scope must be accessed and modified 
+            respectively.  The server must provide interfaces through which
+            various components within the system uniformally perfrom such 
+            operations.  These interfaces and access to the objects implementing
+            them the should be centralized and coherent.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Background</title>
+        
+        <para>
+            The ClientManager interface contains methods used to access a 
+            client's session object.  The ClientManager design promotes 
+            centralized access to ClientSession interfaces through a set of
+            methods designed to retrieve the session using a ClientKey or by
+            using the context of the caller's thread.  The design standardizes
+            and centralizes access to session data without requiring other
+            server modules to pass around the session object or the client key
+            used to retrieve the session.  The design used to manage session 
+            scope parameters would offer the same advantages when used to manage
+            access and modify operation on request scope parameters. 
+        </para>
+        
+        <para>
+            Request information unlike session data changes based on the nature
+            of the protocol operation.  For example a search operation will 
+            contain a search filter and an add operation will not but will have
+            the new entry to add to the DIT.  These differences make it 
+            difficult to devise a standard interface to manage request
+            parameters.  Using an associative key value pair base Map interface 
+            as the basis for the access and storage model standardises the 
+            interface across request.  However the Map interface compromises 
+            security by enabling both access and modification operations on 
+            these parameters regardless of whether they are read only or 
+            mutable.  Use of the Map interface implies weakly typed associations
+            for protocol defined request parameters.  The types of parameters
+            are implicit when accessed or altered as objects in a Map.  Strong
+            explicit types for predefined request parameters should be used if
+            we know the type.  Weak type associations with a Map should only be
+            used for user defined request parameters that are not predefined.
+        </para>
+        
+        <para>
+            The request specific processors within the ProtocolEngine are 
+            responsible for extracting request parameter from a request PDU
+            demarshalled LDAPMessage envelope.  The envelope class is a
+            Java stub class generated by the Snacc ASN.1 compiler.  By leaving
+            parameter extraction up to the processor, the current design 
+            increases the coupling between parameter extraction and request 
+            processing which could be two completely separate phases.  The high
+            degree of coupling imposes a dependency on Snacc API's within the
+            ProtocolEngine.  The only two modules within the server which should
+            have these dependencies are the Encoder and Decoder modules.  It 
+            makes sense to localize parameter extraction from a request PDU 
+            within the decoder module to spare the protocol engine.  The 
+            demarshaling from BER encoded streams handled in the Decoder module
+            should be followed by parameter extraction into a standard request
+            object independent of the ASN.1 BER library used.  The protocol 
+            engine's processors only process requests using these agnostic 
+            request objects without Snacc dependencies, they are not responsible 
+            for managing the creation of the request.  The design extrapolated 
+            to the response phase would require a response object for the 
+            respective request object (if required by the protocol).  The 
+            packaging of response parameters into the Snacc specific LDAPMessage
+            envelope would then be delegated to the Encoder which is already 
+            dependant on Snacc APIs.  The localization of all ASN.1 dependencies
+            to the Decoder and the Encoder module implementations, makes 
+            switching ASN.1 libraries easier by only requiring the Encoder and 
+            Decoder module implementations to be swapped out without affecting
+            the ProtocolEngine.
+        </para>
+            
+        <para>
+            The interfaces for these Snacc independant request and response
+            objects should be kept within the common subproject so both clients
+            and the server can access them.  Final concrete implementations 
+            should reside within the package holding BER library dependant 
+            classes used to extract these parameters or add them to the BER 
+            library specific envelope.  Within there BER library specific 
+            packages the implemenation objects would expose package friendly 
+            methods to build and modify read-only parameters thereby preserving
+            secure access and modification to critical protocol mandated request
+            and response parameters.  Utility classes used to build or extract 
+            response and request parameters from message envelopes composed of
+            ASN.1 compiler generated Java stub classes, needs not reside within
+            the server subproject.  These BER library dependant clases will be
+            used by both clients and server Encoder/Decoder module 
+            implementations and hence are shared across subprojects.  They are
+            best kept within the common subproject close to the BER library
+            dependant stubs which they operate upon.
+        </para>
+        
+        <para>
+            The design goal to standardize request and response scope 
+            parameter handling leads to several architectural benefits.  The
+            benefits and drawbackes are itemized below:
+        </para>
+        
+        <itemizedlist>
+            <title>Benefits</title>
+        
+            <listitem><para>
+            Centralized acess to request and response parameters.
+            </para></listitem>
+
+            <listitem><para>
+            Standard type explict accessors and mutators of request parameters.
+            </para></listitem>
+
+            <listitem><para>
+            Data encapsulation with secure accessor and mutator visibility.
+            </para></listitem>
+            
+            <listitem><para>
+            Diminished dependence on specific (Snacc) BER libraries used.
+            </para></listitem>
+            
+            <listitem><para>
+            Clear distinction between the role of processors and request
+            or response value objects.
+            </para></listitem>
+            
+            <listitem><para>
+            Greater potential for code reuse across clients and server modules.
+            </para></listitem>
+            
+            <listitem><para>
+            Clear, distinct and isolated facility dedicated to request scope
+            management.
+            </para></listitem>
+            
+            <listitem><para>
+            Generally adds more flexibility to the architecture while making it
+            more coherent.
+            </para></listitem>
+            
+            <listitem><para>
+            Enables potential later for processor pooling rather than 
+            instantiation for each request.  May not really be worth that much
+            since processor creation is not expensive.
+            </para></listitem>
+        </itemizedlist>
+        
+        
+        <itemizedlist>
+            <title>Drawbacks</title>
+            
+            <listitem><para>
+                Requires additional interfaces and classes within the common
+                subproject.
+            </para></listitem>
+            
+            <listitem><para>
+                Requires changes to the ClientModule, EncoderModule, 
+                DecoderModule and the ProtocolModule along with a rewrite of the
+                request processors.  SEDA stage events will also need 
+                modification to use these objects instead of the LDAPMessage
+                wrapper generated by Snacc.
+            </para></listitem>
+            
+            <listitem><para>
+                Adds the runtime time and space overhead of copying parameters 
+                into the agnostic request and response objects.  This will be
+                ameliorated by removing this functionality from the processors.
+            </para></listitem>
+            
+            <listitem><para>
+                More work and more code.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Design</title>
+        
+        <para>
+            An extra package has been created for LDAPv3 operation value object
+            interfaces which represent requests and responses.  We'll begin by
+            defining these interfaces within the package org.apache.ldap.common.ops.  A
+            single package rather than one for responses and another for 
+            requests was chosen to minimize the package import statements of
+            dependent code.
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/rootdse-design.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/rootdse-design.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: rootdse-design.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:22  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/03 04:53:51  akarasulu
+backend.xml will be backend-module.xml and rootdse-design.xml will have
+stuff in html file moved into it.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/schema-module.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/schema-module.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,594 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.6 $</revnumber>
+                <date>$Date: 2003/05/03 01:45:23 $</date>
+                <revdescription>
+                    <para>
+$Log: schema-module.xml,v $
+Revision 1.6  2003/05/03 01:45:23  bearcej
+Refix image URLs
+
+Revision 1.5  2003/05/03 01:43:08  bearcej
+Add maven file to help generate server site.
+Modify graphic links again.
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/08 02:29:55  bearcej
+* Clean up project.properties
+* Fix logos in project.xml
+* Fix links to image files in docs
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:24:14  bearcej
+Fixed figure tags to conform to simple docbook.
+Modified Files:
+ Tag: ALPHA-0_7
+    schema-module.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:33  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:22  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.3  2003/03/09 21:50:26  akarasulu
+Ok the schema documentation is done.
+
+Revision 1.1.2.2  2003/03/09 04:59:15  akarasulu
+Checking in a start to the schema manager documentation.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+            The purpose of the SchemaModule is to parse the various published 
+            schema files storing their contents in a form suitable for answering
+            schema related questions.  Schema checking, value normalization and 
+            filter processing as well as most fundamental backend operations 
+            require schema knowledge.
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+
+    <section>
+        <title>Architecture</title>
+
+        <section>
+            <title>Brief Overview of Schema Operations</title>
+
+            <para>
+                Schema information is critical within the server for schema 
+                checking, value normalization, searching and syntax checking.  
+                To define how the SchemaModule or any SchemaManager 
+                implementation is to be designed we must first define how these 
+                aspects relate to servicing protocol requests.
+            </para>
+            
+            <para>
+                Schema's define a set of objectclasses, attributes, syntaxes 
+                and matching rules.  Schema checking in general can be defined 
+                as applying constraints imposed by these definitions.  For 
+                example attribute values are constrained with respect to their 
+                syntax and cardinality.  Entries for example will be constrained
+                to include the MUST list of attributes in order to conform to 
+                the objectclasses they implement and so on.  Schema checking is 
+                applied by default.  If you attempt to add unknown attributes to
+                an entry whose objectclasses do not allow, the operation will 
+                not be permitted by the server.  Likewise, an attempt to add a 
+                String valued attribute which is defined to only support numeric
+                values will not be permitted.  This is what we mean by schema 
+                checking.  The server hence uses these definitions to constrain 
+                entries and the values of their attributes, rejecting any
+                operation that would violate the imposed constraints.
+            </para>
+            
+            <para>
+                Value normalization is critical for correctly searching the 
+                directory.  When entries are added to the directory the values 
+                of their attributes are stored and returned in the format they 
+                were provided preserving both whitespace and case.  However when
+                users attempt to search the directory they provide search 
+                filters with attribute value assertions like (cn=James Brown).  
+                The entry that we intend to recall may have had the cn attribute 
+                set as " james   BROWN".  Because the original user provided cn 
+                was entered in a different case with several spaces between the 
+                two parts of the full name, the match will not occur and the 
+                intended entry will not be returned.  Failure to retrieve the 
+                entry would be the case if value normalization were not used.
+                Fortunately, value normalization has been implemented yet it 
+                requires attribute schema definitions for correct operation.  
+                LDAP has defined the concept of a matching rule specifically to 
+                assist in value normalization.  The matching rule for an 
+                attribute defines how values of that attribute are to be 
+                compared.  In the case of the cn example above, the matching 
+                rule defined for the attribute is called caseIgnoreMatch.  With 
+                this knowledge the server generates normalized keys for matching
+                attributes based on the matching rule.  For the original user 
+                provided cn value of " james   BROWN" the server will create a 
+                normalized key of "james brown".  Since the attribute type is
+                case indifferent, its safe to arbitarily (yet consistantly) 
+                generate keys in one case only.  Also notice that several spaces 
+                in between the two names were consolidated into one space and 
+                spaces at either ends of the string were stripped off.  This 
+                type of white space normalization preserves value tokenization 
+                while removing unnecessary whitespace.  We call the operation a 
+                deep trim as opposed to a superficial trim that removes 
+                whitespace at both ends only.  Unlike simple trims which leave 
+                inner stretches of whitespace, a deep trim, condenses inner
+                whitespace regions into a single space.  When another directory 
+                user tries to search the directory specifically looking for the
+                James Brown example entry with the filter (cn=James Brown), the 
+                filter attribute values are automatically normalized based on 
+                the matching rules of schema definitions.  The effective 
+                normalized filter would then be (cn=james brown).  The value of 
+                the cn filter assertion is compared against the normalized user 
+                provided cn value of the entry to produce a match and return the
+                correct candidate entry.  Without the use of matching rules 
+                defined in schema definitions, correct normalization would not 
+                be possible resulting in a highly input sensitive directory 
+                server.
+            </para>
+            
+            <para>
+                Syntax checking is the process of validating correct values for
+                attributes.  Attributes will need to be constrained according to
+                format, type and size.  Syntaxes define the manner in which 
+                attribute values should be checked for validity.  Again these 
+                rules are defined within published schemas to constrain possible 
+                values.  Examples of syntaxes are Boolean whose IANA assigned 
+                public object identifier (OID) is 1.3.6.1.4.1.1466.115.121.1.7.  
+                Boolean attributes can only have values of "TRUE" or "FALSE".  
+                Any other value for attribute types with this syntax will result
+                in a schema violation - the server will reject any operation 
+                resulting in this violation.
+            </para>
+            
+            <para>
+                LDAP searches must take into account attribute inheritance.  
+                When a search with a filter of (name=abc) is conducted it should
+                return all entries with attributes derived from name.  Meaning
+                entries where cn or sn equal "abc" should be returned.  The name
+                attribute is the least specific base for cn and sn which derive
+                from name.  Attribute inheritance trees are defined within the
+                schema.  Without this schema information correct matching cannot 
+                occur as specified by the protocol.
+            </para>
+        </section>
+        
+        <section>
+            <title>The LDAP Schema Dilema</title>
+            
+            <para>
+                LDAP defines the concept of a RootDSE entry.  The RootDSE entry
+                is where several attributes specific to the directory server or
+                Directory Server Agent (DSA) are stored.  The RootDSE stands for
+                the root DSA Specific Entry (DSE).  It holds for example the 
+                location of a set of replica servers that can be contacted in 
+                case this server is unavailable or unable to service requests 
+                due to heavy load.  One of the attributes contained within the 
+                RootDSE is the subschemasubentry attribute.  All entries in an 
+                LDAP server can contain what is known as the subentrysubschema 
+                attribute.  The attribute is intended to point to or refer to a 
+                local entry which stores amongst other things the schema 
+                definitions constraining the refering entry.  The 
+                subschemasubentry attribute is single valued so the RootDSE and
+                any other regular entry can only contain a single value for it.
+                This makes sense since an entry should be governed by only one
+                schema.  If more than one set of schema definitions governed the
+                composition of an entry inconsistant definitions could occur.  
+            </para>
+            
+            <para>
+                The intention of having a subschemasubentry within the RootDSE 
+                was to enable the discovery of the governing directory schema.
+                This implies a one to one relationship between a schema and a
+                directory server.  In fact most LDAPv3 servers manage a single
+                common schema for the entire Directory Information Tree (DIT) of
+                the server.  It is a common practice to use cn=schema for the
+                value of the subschemasubentry.  Novell's NDS and the Netscape 
+                Directory Server (a.k.a. SUN One Directory Server) store schema
+                definitions in this entry with a DN of cn=schema.  Serveral 
+                other commercial servers do the same.
+            </para>
+            
+            <para>
+                This is a very limiting aspect to LDAP.  The explosion of
+                published schemas stuffed into the cn=schema entry has conjested 
+                the entry with attributes for objectclasses, attribute 
+                definitions and syntaxes not to mention ACI attributes that are 
+                also injected into the entry.  Pulling down the massive entry 
+                takes far too long incomparison to the average sized entries in
+                the DIT.   Sure filters can be used to bring down subsets of the
+                entry as needed, however this does not resolve the problem fully
+                since several values for attributes exist and entire definition
+                bodies are embedded within these values as large text objects.  
+                Such selective filters on the entry still need to use substring 
+                matching which is the least efficient and accurate manner for 
+                searching the entry other than using the approximate search
+                operator.  Overall the cn=schema entry is massive with hundreds
+                if not thousands of attributes, and it is very difficult to 
+                search the contents of this entry efficiently and accurately to 
+                answer schema related questions.
+            </para>
+            
+            <para>
+                Another limitation imposed by storing all schema information in
+                one place is the implication that only one schema governs the
+                composition of all entries within the directory.  The need to
+                constrain different regions of the tree through the definition
+                of alternative schemas will inevitably arise.  It is very 
+                unreasonable to consolidate and limit all schema definitions to
+                one.  What's the point of having the potential for every entry 
+                to contain a subschemasubentry attribute?  Why enable the 
+                attribute in every entry if there can only be one schema defined
+                for the entire DIT?  By convention, the entry referred to by the
+                DN value stored in the RootDSE's subschemasubentry attribute 
+                could be implied as the one place for the storage of schema 
+                definitions, since only one schema governs the entire directory.
+                This contradiction leads us to believe that the protocol at its
+                inception borrowed too little from its more robust parent, the
+                X.500 directory.  The subschemasubentry concept made its way 
+                into LDAP but not fully.  This is why LDAP servers do not 
+                provide the ability to manage multiple regions governed by 
+                different schema definations.  They do however provide the 
+                ability to have different entries point to multiple schemas by 
+                allowing all to have a subschemasubentry attribute.
+            </para>
+            
+            <para>
+                LDAP never clearly defined a means to managing schema data in 
+                separate regions of the directory tree - this was left up to the
+                server implementation if supported at all.  The notion of 
+                partitioning the directory tree into regions managed by 
+                different schemas was very explicitly defined by the X.500 
+                standard in what they called Subschema Authoritative Areas or
+                SAAs.  These regions were defined at various points in the 
+                DIT to mandate schema constraints.  The coverage of the area
+                was defined using a subtree specification and SAAs could be 
+                located anywhere and occupy any subtree shape imaginable based
+                on the parameters of the specification.  Unlike X.500 LDAP lacks
+                these rich constructs.
+            </para>
+            
+            <para>
+                While designing the SchemaManager service we kept these short
+                falls in mind with the intention of alleviating them if not 
+                irradicating them.  The need to enable multiple schemas 
+                restricted to specific regions of the DIT was too compelling to
+                ignore.  At a bare minimum we wanted to enable different schemas
+                for DIT partitions or in otherwords backends of the server while
+                remaining protocol compliant giving users the same environment
+                they are accostomed to.  Our attempt to do so is incomplete and
+                an ongoing process.  Before the protocol compliant alpha 
+                release we would like to enable a super schema entry at 
+                cn=schema for default schema support in the expected fashion. We
+                would also like to enable each backend to have its own schema
+                for the time being until a more complete mechanism for schema
+                management can be established.  While stuck in this limbo, we
+                can investigate further constructs and mechanisms within X.500
+                which can be incorporated into the server while remaining in 
+                full compliance with the LDAPv3 specifications.  The design 
+                described for now regarding the SchemaManager and its associated
+                helper interfaces is mostly an intermediate design.
+            </para>
+                
+            <para>
+                Rather than implement full blown SAAs we decided to borrow a
+                little from them.  We simply assigned an SAA to a DN and 
+                considered the subtree of the SAA to encompass everything below
+                it.  In the end we fell back on just requiring an SAA to be 
+                defined for every naming context or backend suffix to be 
+                attached to the server.  Hence every backend in the server must 
+                have its own set of schema definitions.  Was this the correct 
+                way to proceed?  Probably not!  But it was done and for the time 
+                being it will stay until we refactor the design into a more 
+                accurate one.  Also note that for the time being no schema entry
+                referred to by the subschemasubentry exists at the present time,
+                so even though schemas are applied one for each backend, they 
+                nor the superset of them are published to the outside world.
+                With these facts noted we shall continue in the next section to
+                describe the interfaces within the schema package.
+            </para>
+        </section>
+        
+        <section>
+            <title>
+                SchemaManager Service Interface And Its Associated Helpers
+            </title>
+            
+            <para>
+                The SchemaModule implements the SchemaManager service interface
+                which declares two methods to access a Schema object: 
+                getSchema() and getCompleteSchema().  The getSchema() method,
+                requires a String argument specifying a distinguished name.  As
+                a consequence of having implementations possibly parse the 
+                String DN argument into a Name, getSchema() throws a 
+                NamingException.  As can be inferred getSchema() retrieves the 
+                Schema instance in effect at a point (or entry) within the 
+                directory specified by DN.  The returned schema is the schema
+                defined by the SAA at that suffix DN.  The other method, 
+                getCompleteSchema() retrieves the union of all the schema object 
+                definitions within the entire directory as one Schema instance.
+                The returned Schema representing the superset of schema 
+                definitions would be equivalent to the content stored by a
+                cn=schema entry if one existed.
+            </para>
+            
+            <para>
+                The role of the SchemaManager service is simple.  It is a 
+                location specific Schema factory.  The Schema interface is the
+                contract through which answers to schema related questions are
+                obtained.
+            </para>
+            
+            <para>
+                Every aspect with regard to the effective schema constraining
+                a point in the directory can be assertained by methods on the 
+                Schema interface.  These methods enable most of the schema 
+                operations required for syntax checking, attribute value 
+                normalization, and schema checking to detect object class 
+                violations.  Access to other interfaces are provided to perform
+                these operations via the Schema.
+            </para>
+            
+            <para>
+                The Schema interface enables access to two types of NameParsers
+                used to parse a String representation of a DN into a Name.  The 
+                getNameParser() method returns a NameParser that does not 
+                normalize name component attribute identifiers or their values.
+                The getNormalizingParser() method returns a NameParser that does
+                normalize attribute identifiers and values based on the 
+                attribute definitions in the Schema instance returning the 
+                parser.  Note that for each name component attribute value pair 
+                within a distinguished name a different normalization function
+                may need to be applied.  The normalizing name parser must lookup
+                the normalizer to use for each of the component attributes.  Of 
+                course this information is available within the Schema that 
+                creates the normalizing name parser.
+            </para>
+            
+            <para>
+                Access is also provided to an LdifParser and an LdifComposer.  
+                These interfaces define methods for taking a MultiMap to and
+                from an LDIF representation.  A MultiMap is a extention on the
+                Map interface to allow a single key to have multiple values 
+                defined for it.  It is ideal for storing attribute values since 
+                attributes can have a single value or have multiple values.  The
+                MultiMap interface is defined within the Apache Commons 
+                Collections package.
+            </para>
+            
+            <para>
+                Another interface accessible through the Schema.getNormalizer()
+                method is Normalizer.  Normalizers are attribute specific.  They
+                transform the values of String attributes according to the 
+                matching rules defined for them.  For example some default 
+                normalizers for case insensitive Strings attributes are defined 
+                to do a deepTrimToLower and others that are for case sensitive 
+                Strings may perform a deepTrim without transforming alpha 
+                characters into lower case.
+            </para>
+            
+            <para>
+                The Schema interface itself defines several other methods that 
+                test, or transform values of a specific attribute type.  Another 
+                Schema method is provided to apply a syntax check on an entire 
+                entry.
+            </para>
+        </section>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <section>
+            <title>Schema Files</title>
+            
+            <para>
+                Presently, schema definitions are stored in schema files.  These
+                static ascii files use the standard <ulink url=
+                "http://ldap.akbkhome.com/attribute/attributeTypes.html"> 
+                Attribute Type Description </ulink> and <ulink url=
+                "http://ldap.akbkhome.com/attribute/objectClasses.html">Object 
+                Class Description</ulink> syntax as specified within <ulink url=
+                "http://www.faqs.org/rfcs/rfc2252.html"> RFC2252</ulink>.  They
+                are slightly modified to facilitate parsing ease by prefixing
+                the descriptions with either a 'attributetype' or 'objectclass' 
+                marker.  The format as well as the various files used were 
+                adopted from the definitions managed by the <ulink url=
+                "http://openldap.org">OpenLdap</ulink> effort.
+            </para>
+            
+            <para>
+                The definitations are categorically separated into separate 
+                files one for each major group of definitions.  For example the
+                core set of definitions in RFC2252 are resident in a schema file
+                named core.schema.  Other popular and published type 
+                descriptions exist like the java schema and the corba support
+                schema.  The contents of these files are parsed and stored in 
+                AttributeSpec and ObjectClassSpec beans.
+            </para>
+        </section>
+        
+        <section>
+            <title>Initialization Time</title>
+            
+            <para>
+                The SchemaModule creates various Schema instances as a 
+                consequence of initialization.  These Schema objects are 
+                accessible using a DN. Their contents are based on the 
+                contents of the parsed schema files and the SchemaManaqer's 
+                configuration section within the config.xml file.  The 
+                configuration for the SchemaManager specifies the set of schema
+                files that can be used to define SAAs.  The files are referred 
+                to within schema elements which assigns a schema name to the
+                file.  At configuration time the very first task performed is
+                the parse of these files.  For each file a Schema object is 
+                populated with AttributeSpec and ObjectClassSpec objects.  While
+                filling the target Schema object, a superset Schema object 
+                returned using the getCompleteSchema() method, is populated as
+                well.  The complete schema not only fulfills the needs for a 
+                complete schema hangling off of the cn=schema entry, but also
+                allows for cross referencing between schema files.  Sometimes
+                an attribute or objectclass is defined using existing core 
+                schema attributes and objectclasses.  Resolution of values using
+                parent objectclasses and attributes is made possible by this
+                complete union schema of all schema definitions stored accross
+                these files.
+            </para>
+        
+            <para>
+                Once all schema files are parsed a normalization configuration
+                element section is used to construct Normalizers for the various
+                matching rules the server must implement.  Next a configuration
+                section for user defined syntax checkers is used to create 
+                syntax mandating elements used by the schema to check attribute
+                values for correct syntax usage.  Finally once all schema 
+                objects have been populated with their specification beans, 
+                required normalizers and syntax checkers the SAAs of the 
+                configuration are created.
+            </para>
+            
+            <para>
+                SAA elements define the set of schema object that are valid 
+                below and at a point within the directory.  Every descendent
+                entry at and under the SAA DN will be constrained by the set
+                of schema objects defined.  The SAA element contains a set of
+                references to the schema files parsed.  For each SAA element a
+                new Schema implementation is instantiated and populated with the
+                AttributeSpec beans, ObjectClassSpec beans, Normalizers and 
+                syntax checkers of the reference Schema objects.  Hence an SAA
+                is just another Schema that is the union of several schema file
+                Schemas.
+            </para>
+        </section>
+        
+        <section>
+            <title>Runtime</title>
+            
+            <para>
+                At runtime several Maps within the SchemaImpl instances are 
+                already populated.  These set of Maps are used to do fast 
+                lookups to access AttributeSpecs,  ObjectClassSpecs, Normalizers
+                and SyntaxCheckers.  The various methods on the Schema interface
+                are implemented using these Maps within the SchemaImpl class.
+            </para>
+        </section>
+        
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+            Eventually we would like to solve the schema dilema for LDAP 
+            elegantly without breaking with protocol requirements.  No matter
+            what the same referrence to the superset of schema elements must be
+            maintained within the entry referred to by the subschemasubentry 
+            attribute in the RootDSE.  At the present moment we have delayed the
+            implementation of this schema administration entry.  It must at some
+            point be implemented to comply with the standard mode of schema 
+            inquire to be familiar to users.  However nothing is stopping us 
+            form making this entry the suffix to an entire backend under which 
+            other entries can reside to yeild specific information in a 
+            searchable format concerning schema objects and SAAs.  For example 
+            if we were to use cn=schema as the value for the subschemasubentry
+            attribute within the RootDSE, then cn=schema can be the suffix of 
+            a backend with entries below.
+        </para>
+
+        <para>
+            At the present time we do not have a clear understanding of exactly
+            how we intend to structure this tree.  We do know that we want to 
+            enable the decomposition of attribute type and objectclass 
+            descriptions into searchable entries.  A special schema can be 
+            defined to store schema information itself.  This way the search 
+            machinery of the backend can be used to answer complicated questions
+            regarding attribute and objectclass relationships in a standard way.
+            Otherwise we will have to devise Maps within the Schema 
+            implementation to correlate descriptions with one another.  We would
+            also like to search descriptions and SAA specifications without 
+            requiring clients to parse their syntactic representation.  Breaking
+            these specifications down into entries solves these problems.  While 
+            supporting these extra features to aid in schema support we would 
+            like to provide the expected constructs for backwards compatability.
+            Eventually we hope that we can persuade the LDAP community to see 
+            the value proposition of schema descriptions specified as entries
+            with a deep schema administration context rooted at cn=schema or 
+            what ever is specified by the subschemasubentry within the RootDSE.
+        </para>
+        
+        <para>
+            Just for fun we envisioned the following DIT structure to a schema
+            administration context.  The diagram below represents the DIT.
+            Imagine for a moment that cn=schema were the root of the schema
+            administration naming context.  Under it would reside containers
+            for entries describing attribute types, objectclasses, syntaxes,
+            and matching rules.  Also located under cn=schema could reside SAA
+            specification describing the subtree of authority and a schema 
+            definition set of the schema objects composing the SAA.  Questions
+            as to which SAA governs the schema of an entry can be used in a 
+            filter to search for the appropriate SAA in charge.  Hence the 
+            effective subschemasubentry value if asked for of an entry can be
+            extracted at entry retrival time by searching the ou=SAA branch.
+        </para>
+        
+        <figure>
+            <title>Speculation on a Administrative Schema DIT Structure</title>
+            <graphic fileref="../images/AdminSchemaContext.gif"/>
+        </figure>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+            Incomplete since the RootDSE subschemasubentry attribute referral to
+            a schema description entry does not exist.  We need a cn=schema 
+            entry to present attributeType and objectClasses attributes in the
+            proper expected syntax.
+        </para>
+        
+        <para>
+            Messy adhoc implementation with maps all over the place.
+        </para>
+        
+        <para>
+            The inheritance thing does not work and there are a number of 
+            bugs where cross schema references do not resolve.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/seda-implementation.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/seda-implementation.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Module Implementation</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.3 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: seda-implementation.xml,v $
+Revision 1.3  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.1  2003/03/10 23:24:22  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.1  2003/03/03 04:49:25  akarasulu
+Added as placeholders for now.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+        <para>
+        </para>
+    </abstract>
+    
+    <section>
+        <title>Document TODOs:</title>
+        <itemizedlist>
+            <listitem><para>
+                Add diagrams.
+            </para></listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Implementation</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+    <section>
+        <title>Future</title>
+        
+        <para>
+        </para>
+
+        <para>
+        </para>
+    </section>
+
+    <section>
+        <title>Faults</title>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+        
+        <para>
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/server-architecture.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/server-architecture.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,613 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+<article class="whitepaper">
+    <title>Server Architecture</title>
+    
+    <articleinfo>
+        <author><othername>akarasulu</othername></author>
+        <editor><othername>$Author: bearcej $</othername></editor>
+        <revhistory>
+            <revision>
+                <revnumber>$Revision: 1.4 $</revnumber>
+                <date>$Date: 2003/05/03 01:21:32 $</date>
+                <revdescription>
+                    <para>
+$Log: server-architecture.xml,v $
+Revision 1.4  2003/05/03 01:21:32  bearcej
+Remove tabs from doc files and fix linefeeds.
+
+Revision 1.3  2003/04/21 21:11:50  bearcej
+
+* Fix broken links in documentation.
+
+Revision 1.2  2003/03/23 13:24:46  akarasulu
+Added these files from the ALPHA-0_7 branch.
+
+Revision 1.1.2.3  2003/03/15 17:21:58  bearcej
+Fixed abstract tag.
+Modified Files:
+ Tag: ALPHA-0_7
+    server-architecture.xml
+
+Revision 1.1.2.2  2003/03/10 23:43:33  akarasulu
+Moved links so that image references point to /image/design.  Note that
+references do not have a [.] in front since the maven driven transforms
+automatically append [.] to references.
+
+Revision 1.1.2.1  2003/03/10 23:24:22  akarasulu
+Moved design documentation from docs/design to src/docbook/design.
+
+Revision 1.1.2.9  2003/03/02 00:37:32  akarasulu
+Adjusting spacing.
+
+Revision 1.1.2.8  2003/03/02 00:32:39  akarasulu
+Completed listener documentation but needs some work and added the article
+info tag to both these document.  Also flaged these docs as whitepapers.
+
+                    </para>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </articleinfo>
+
+    <abstract>
+    <para>
+        The server consists of a set of loosely coupled modules.  All server
+        modules are not created equally.  Some modules are stages that take
+        part in the Staged Event Driven Architecture (SEDA) aspect of the 
+        LDAPd server.  Some modules are startable, having a single driver thread.
+        The simplest modules have no driver at all relying on the threads 
+        of caller modules to drive their workload.  This document describes the
+        modular structure of the server without delving deep into each specific 
+        module, but rather defining what a module is, and the various types of 
+        modules within the server.  Other documents are dedicated to the 
+        implementation of each specific module.
+    </para>
+    </abstract>
+    
+    <section>
+        <title>What is a Module?</title>
+        
+        <para>
+            LDAPd is composed of modules, but what exactly is a module?  The
+            definition is partly defined by the LDAPd project and partly defined
+            by the Avalon Framework.  Avalon defines lifecycle methods for 
+            components that fit into a framework.  Components define interfaces
+            used to manage lifecycle operations.  These lifecycle aspects are 
+            then automatically managed by a component conatiner using the 
+            Inversion of Control Pattern.  Inversion of Control enables the
+            construction of reusable loosely coupled components.  Avalon 
+            Framework specifies the various lifecycle methods using interfaces
+            that components may have.  The framework is just that, an API mostly
+            composed of interfaces.  The designers of Avalon have thought of 
+            all the possible generalized lifecycle methods, components may have
+            and have forged a set of interfaces for component designers to use.
+        </para>
+        
+        <para>
+            The concept of an LDAPd module is defined in terms of Avalon 
+            Framework interfaces.  In terms of lifecycle behavoirs, an LDAPd 
+            module is a log enabled, configurable, initializable, startable, 
+            and coincidentally, stopable, thread safe component with potential 
+            dependencies on other components within the server.  The Avalon 
+            Framework interfaces and their methods define these lifecycle 
+            behavoirs.  We have programatically defined an LDAPd module as an 
+            interface that extends many Avalon Framework interfaces.  Not 
+            surprisingly, the name of the interface is Module and it is located
+            in the org.apache.eve package.  All LDAPd modules must implement this 
+            interface.  The Module interface simply states the lifecycle methods
+            a module must implement.  The set of Avalon Framework interface's 
+            extended by the Module interface are listed below:
+        </para>
+
+        <itemizedlist>
+            <listitem><para>Startable</para></listitem>
+            <listitem><para>ThreadSafe</para></listitem>
+            <listitem><para>LogEnabled</para></listitem>
+            <listitem><para>Serviceable</para></listitem>
+            <listitem><para>Configurable</para></listitem>
+            <listitem><para>Contextualizable</para></listitem>
+            <listitem><para>Initializable</para></listitem>
+        </itemizedlist>
+        
+        <para>
+            Besides mandating the lifecycle functions, the Module interface 
+            also defines extra methods used to query information regarding the 
+            role, name and implementation of a Module.  More than one module 
+            implementation can exist for a module service type, and the specific
+            implementation chosen can be delayed until runtime.  Besides the
+            Module interface, a base AbstractModule class is defined as an 
+            adapter which correctly handles most of the lifecycle methods of a
+            module.  Subclasses of AbstractModule are expected to implement 
+            some criticle and highly specific interface methods to be concrete.
+        </para>
+    </section>
+
+    <section>
+        <title>Core Service Interfaces</title>
+        
+        <para>
+            Building a module for the sake of implementing the required 
+            lifecycle interfaces does not make sense.  A module needs to do 
+            something by providing a service.  The Avalon Framework defines the 
+            concept of a service interface for components.  Publicly exposed
+            service interfaces provide methods that callers invoke to interact 
+            with the service.  The service interface in this way defines the 
+            role of the module within the server.  The service interfaces are 
+            completely decoupled and independant of the lifecycle methods.
+        </para>
+        
+        <para>
+            LDAPd defines a set of core service interfaces which must be 
+            implemented as server modules.  These are the set of manditory 
+            services required to make the server work.  These services are
+            listed below:
+        </para>
+
+        <table frame='all'><title>Mandarory LDAPd Services</title>
+            <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+                <colspec colname='Interface'/>
+                <colspec colname='Package'/>
+                <colspec colname='Description'/>
+                <thead>
+                    <row>
+                        <entry>Service Interface</entry>
+                        <entry>Java Package</entry>
+                        <entry>Service Description</entry>
+                    </row>
+                </thead>
+                <tbody>
+                    <row>
+                        <entry>UnifiedBackend</entry>
+                        <entry>org.apache.eve.backend</entry>
+                        <entry>The junction where all backends connect.</entry>
+                    </row>
+                    <row>
+                        <entry>ClientManager</entry>
+                        <entry>org.apache.eve.client</entry>
+                        <entry>Maintains and tracks client sessions.</entry>
+                    </row>
+                    <row>
+                        <entry>Decoder</entry>
+                        <entry>org.apache.eve.decoder</entry>
+                        <entry>Demarshals ASN.1 BER LDAPv3 messages</entry>
+                    </row>
+                    <row>
+                        <entry>Encoder</entry>
+                        <entry>org.apache.eve.encoder</entry>
+                        <entry>Marshals ASN.1 BER LDAPv3 messages</entry>
+                    </row>
+                    <row>
+                        <entry>EventManager</entry>
+                        <entry>org.apache.eve.event.protocol</entry>
+                        <entry>
+                            Central point for firing and recieving protocol 
+                            events - not related to stage events.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>InputManager</entry>
+                        <entry>org.apache.eve.input</entry>
+                        <entry>
+                            Detects input on client channels to invoke the 
+                            decoder.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>Encoder</entry>
+                        <entry>org.apache.eve.encoder</entry>
+                        <entry>Marshals ASN.1 BER LDAPv3 messages</entry>
+                    </row>
+                    <row>
+                        <entry>JndiProvider</entry>
+                        <entry>org.apache.eve.jndi</entry>
+                        <entry>
+                            Factory for internal serverside JNDI LdapContexts
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>ServerListener</entry>
+                        <entry>org.apache.eve.listener</entry>
+                        <entry>
+                            Detects initial connections between the client and 
+                            the server.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>OutputManager</entry>
+                        <entry>org.apache.eve.output</entry>
+                        <entry>
+                            Handles response PDU buffer streaming to the client.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>ProtocolEngine</entry>
+                        <entry>org.apache.eve.protocol</entry>
+                        <entry>
+                            The heart of the server which processes protocol
+                            requests to generate the protocol responses if 
+                            required.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>SchemaManager</entry>
+                        <entry>org.apache.eve.schema</entry>
+                        <entry>
+                            Maintains and stores schema related information
+                            as specified in the config.xml and the various 
+                            schema files associated with subschema authoritative
+                            areas.
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>AuthenticationManager</entry>
+                        <entry>org.apache.eve.security.auth</entry>
+                        <entry>
+                            Manages simple authentication on LDAP bind 
+                            operations both for admin and non-admin users.
+                        </entry>
+                    </row>
+                </tbody>
+            </tgroup>
+        </table>
+    </section>
+    
+    <section>
+        <title>Staged, Executable and Simple Modules</title>
+        
+        <para>
+            As we mentioned before, not all modules are created equal.  Some
+            modules participate in the SEDA aspect of the server.  These modules
+            are stages and must in addition to the Module interface implement 
+            the Stage interface or extend a base class in the org.apache.eve.seda 
+            package.
+        </para>
+        
+        <para>
+            Without replicating Matt Welsh's paper on SEDA we'll consisely 
+            define a stage as an event queue, a driver thread and a worker
+            thread pool.  Stages recieve events which are popped off their 
+            event queues and handed off to a worker thread for processing.  
+            Events this way are processed in parallel and asynchronously.  In
+            SEDA architectures, stages compose event processing pipelines that
+            often out perform their strictly threaded or strictly event driven
+            counterparts.
+        </para>
+        
+        <para>
+            Stages in LDAPd are modeled exactly as defined above.  They have an 
+            event queue, a driver thread and a worker thread pool.  Within the
+            LDAPd server the following core service interfaces are presently 
+            implemented as stages composing the request processing pipeline:
+        </para>
+        
+        <itemizedlist>
+            <listitem><para>ClientManager</para></listitem>
+            <listitem><para>OutputManager</para></listitem>
+            <listitem><para>Encoder</para></listitem>
+            <listitem><para>Decoder</para></listitem>
+            <listitem><para>ProtocolEngine</para></listitem>
+        </itemizedlist>
+
+        <para>
+            These service interfaces may not remain stages for long.  Presently
+            the new IO (java.nio) functionality for nonblocking IO has not been 
+            implemented.  Once implemented stages may split or fuse together. 
+            Some modules may remain but may no longer become stages.  This is 
+            dependent on how the architecture progresses.  What is certain is 
+            that stages will be present as the components of the mature server.
+        </para>
+        
+        <para>
+            Simple modules, that are not stages also exist.  The following 
+            service interfaces are implemented as simple modules without the use
+            of any threads other than the thread of the caller to do work:
+        </para>
+        
+        <itemizedlist>
+            <listitem><para>AtomicBackend</para></listitem>
+            <listitem><para>UnifiedBackend</para></listitem>
+            <listitem><para>EventManager</para></listitem>
+            <listitem><para>JndiProvider</para></listitem>
+            <listitem><para>SchemaManager</para></listitem>
+            <listitem><para>AuthenticationManager</para></listitem>
+        </itemizedlist>
+
+        <para>
+            Some service interfaces are not implemented as stages, or as simple
+            modules.  These implementations use one or more threads to perform
+            some work outside of the thread of any caller.  There are two such
+            service interfaces.  First the InputManager, which detects IO on 
+            client connections uses a pool of threads to listen for client 
+            input stream activity.  This is a temporary work around until the
+            module is implemented using selectable channels within the new IO
+            packages of the JDK 1.4+ platforms.  Once channels and channel 
+            selection is used to implement nonblocking IO, one single thread 
+            can be used by this module to detect IO on any number of clients
+            concurrently.  This is where and when the true power of SEDA will
+            reviel itself, until then we use this classic implementation.  
+        </para>
+        <para>
+            The other service interface which is implemented neither as a stage 
+            nor a simple module, is the ServerListener module.  Currently the 
+            server listener uses a single thread to listen to a single port for 
+            incomming connections.  Presently it cannot listen to more than one
+            port.  It can be extended to listen to more ports by either using
+            non-blocking selectors on multiple server socket's bound to more 
+            than one port, or it can use one pooled thread per server socket.
+            Nevertheless both these service interface implementations will 
+            change, without changing the interface itself, to reduce the number
+            of threads used while increasing concurrency.  These modules may also
+            fuse together using a single channel selector for both client accept 
+            and input IO events.
+        </para>
+    </section>
+    
+    <section>
+        <title>Service Interfaces and Modules</title>
+        
+        <para>
+            Every core service interface defined is implemented as a server 
+            module whether it be as a simple module, a staged module or other.  
+            Each interface has a single implementation instance at runtime with 
+            the exception of AtomicBackends.  Several AtomicBackend 
+            implementations may exist for various entry backing stores.  
+            Currently, there are three different AtomicBackend types: the 
+            modjdbm, modjdbc and the BerkeleyDB backend.  Multiple backend
+            instances of the same type or of different types can coexist in the
+            same server process instance.  Each AtomicBackend instance is only 
+            required to have a unique suffix DN to differentiate itself from 
+            other backends.  One or more AtomicBackend instances hang off of the 
+            UnifiedBackend service which is implemented by the NexusModule.  
+            Below we list the various service interfaces and their corresponding 
+            Module implementations excluding the AtomicBackend implementations:
+        </para>
+        
+        <itemizedlist>
+            <listitem>
+                <para>NexusModule implements UnifiedBackend</para>
+            </listitem>
+            <listitem>
+                <para>ClientModule implements ClientManager</para>
+            </listitem>
+            <listitem>
+                <para>DecoderModule implements Decoder</para>
+            </listitem>
+            <listitem>
+                <para>EncoderModule implements Encoder</para>
+            </listitem>
+            <listitem>
+                <para>EventModule implements EventManager</para>
+            </listitem>
+            <listitem>
+                <para>InputModule implements InputManager</para>
+            </listitem>
+            <listitem>
+                <para>OutputModule implements OutputManager</para>
+            </listitem>
+            <listitem>
+                <para>JndiProviderModule implements JndiProvider</para>
+            </listitem>
+            <listitem>
+                <para>ListenerModule implements ServerListener</para>
+            </listitem>
+            <listitem>
+                <para>ProtocolModule implements ProtocolEngine</para>
+            </listitem>
+            <listitem>
+                <para>SchemaModule implements SchemaManager</para>
+            </listitem>
+            <listitem>
+                <para>AuthenticationModule implements AuthenticationManager
+                </para>
+            </listitem>
+        </itemizedlist>
+    </section>
+    
+    <section>
+        <title>Request Processing</title>
+        
+        <para>
+            Without using a highly detailed sequence diagram we shall represent 
+            at a very high level the flow of SEDA based events within the system 
+            while processing requests that have a single response. 
+            <ulink url="images/ReqRespStageFlow.gif">Figure I</ulink> 
+            is a very high
+            level stage to stage processing sequence for requests that have a
+            single response.  LDAPv3 abandon and unbind requests have no 
+            responses and LDAPv3 search requests may have one or more responses
+            so these requests are not entirely represented in this diagram.  
+            Keep in mind that this sequence diagram trivializes the staged 
+            processing by only showing the stage modules and the events they
+            generate within the pipline.  Other modules that are used indirectly
+            while servicing these requests are not shown.  More detail 
+            concerning module interactions downstream of the ProtocolEngine are
+            provided in the protocol engine's implementation documentation where
+            each request processor implementation is outlined.
+        </para>
+
+        <para>
+            Briefly, Abandon and Unbind requests never produce a response and 
+            Search requests have the potential of generating more than one 
+            response.  Reponseless requests simply stop processing after the 
+            respective request processor completes processing within the 
+            ProtocolModule. The Search request is more complex requiring 
+            synchronized delivery of messages in a specific order.  Special 
+            methods are used to bypass staged event handling both in the 
+            EncoderModule and in the OutputModule when search requests with more 
+            than one response are processed.  Serial delivery of entry responses 
+            in a search requires special synchronous pathways through the 
+            Encoder and Output modules.  The last search done reponse, however 
+            goes through the standard staged event handling mechanism.  Again,
+            Search, Abandon and Unbind LDAPv3 request processing is discussed 
+            in more detail within the low level implementation document for the
+            ProtocolModule.
+        </para>
+
+        <section>
+            <title>Input Detection Stage</title>
+            <para>
+                In the solid state, when all modules have started up, and after 
+                a client has established a connection, an input handler assigned 
+                to every client connection, blocks waiting for IO activity on 
+                the input stream of the client socket.  Once incomming data is 
+                detected an InputEvent is generated and enqueued on the event 
+                queue of the DecoderModule.
+            </para>
+        </section>
+        <section>
+            <title>
+                Protocol Data Unit (PDU) Decoding Stage (PDU Demarshaling)
+            </title>
+            <para>
+                Once the InputEvent is dequeued and processed a decoding occurs 
+                while reading the input stream to build a LDAP request message 
+                envelope.  This stage demarshals the incoming PDU on the client 
+                input stream using Binary Encoding Rules (BER).  Once the 
+                demarshaling is complete a RequestEvent is assembled with the 
+                demarshalled request PDU and enqueued onto the ProtocolModule 
+                stage for handling and response generation.
+            </para>
+        </section>
+        <section>
+            <title>Request Protocol Handling Stage</title>
+            <para>
+                Once the RequestEvent is dequeued by the ProtocolModule's driver
+                thread a protocol request processor is created to process the 
+                request PDU.  A stage worker pool thread is used to drive the 
+                processing.  Depending on the nature of the protocol request 
+                various modules downstream from protocol engine may be directly 
+                or indirectly called upon to complete the request.  Most of the 
+                time the NexusModule is called which routes requests to the 
+                appropriate target backend based on the backend suffix.  Some 
+                protocol requests are special in that they do not return a 
+                response or potentially return more than one response.  Such
+                protocol request types are refered to specifically in the 
+                protocol engine documentation.  For the majority of request 
+                types the processors generate a response message envelope to 
+                be delivered back to the client on the socket output stream.
+                The protocol engine can differentiate between those request 
+                types that generate a response and those that do not.  After, 
+                and if, a response is generated, it is packaged within a newly
+                created ResponseEvent.  This event is enqueued onto the Encoder
+                stage's event queue.
+            </para>
+        </section>
+        <section>
+            <title>Response Encoding Stage (PDU Marshaling)</title>
+            <para>
+                Once the ResponseEvent is popped off of the event queue by the
+                driver thread of the EncoderModule, the packaged response 
+                message envelope (LDAPMessage instance) is accessed.  The object
+                is marshalled into a BER encoded buffer stream.  A input stream
+                to this buffer is created and packaged within a OutputEvent 
+                which is then enqueued on the event queue of the OutputModule
+                stage.
+            </para>
+        </section>
+        <section>
+            <title>Output Handling Stage</title>
+            <para>
+                Once the OutputEvent is popped off of the event queue by the
+                driver thread of the OutputModule, the encoded response PDU can 
+                be pumped from the buffer into the OutputStream of the client.
+                Synchronized access to the OutputStream of the client is 
+                acquired from the ClientModule using the ClientKey packaged in
+                the OutputEvent.  A worker thread form the stage's worker thread
+                pool is assigned to pump the bytes stored in the BER encoded 
+                buffer accessed via an InputStream into the OutputStream of 
+                the client.  This is not an optimal implementation but it works 
+                for now allowing for full system integration testing.  
+                Optimization efforts specifically targeting the JDK1.4 platform
+                (using non-blocking selectors and fast direct memory buffers) 
+                will be underway within the first beta releases.
+            </para>
+        </section>
+    </section>
+
+    <section>
+        <title>Module Interdependence</title>
+        
+        <para>
+            Modules within the server indirectly depend on one another since 
+            they must call each other's service interface methods to process 
+            client requests.  Modules depend on service interfaces (ROLE's), not 
+            on module's implementing those interfaces.  This keeps the modules
+            decoupled and is a motif brought about through the use of Avalon.
+            Cyclic dependencies can however create a chicken and egg problem for 
+            the server kernel (container) used to fire up the server's modules.  
+        </para>
+        
+        <para>
+            The LDAPd server avoids these cyclic dependencies by designating the 
+            ClientModule as a master module and those that depend on it in a 
+            cycle as ClientManagerSlaves.  Many modules need to access client
+            session information managed by the ClientModule.  The ClientModule
+            however passes on requests to the InputModule, which later passes
+            on requests to the ProtocolModule and so on until the OutputModule.  
+            If any of these modules downstream of the ClientModule need to 
+            access the client's session or request its termination they need to
+            make calls to the ClientModule's service interface.  This imposes a
+            cyclic dependency when standard container mechanisms are used 
+            to get handles on the services an interface modules depend upon.  In 
+            Avalon Framework, the Serviceable interface (required by all LDAPd
+            Modules) has the service method, which is the standard mechanism for
+            getting a handle on another service.  When containers detect cycles
+            by monitoring the service lookups made by a Serviceable component,
+            they complain and reject initialization.  Our little workaround for
+            these unavoidable cyclic dependencies is to, in some respects, 
+            violate, yet formalize a registration mechanism outside of the 
+            Serviceable paradigm, thereby bypassing cycle detection in some 
+            pathological cases.
+        </para>
+        
+        <para>
+            Upon recommendations from the Avalon team we constructed a special
+            ClientManagerSlave interface.  This interface has a single method
+            which is used to register the ClientModule (a.k.a. the 
+            ClientManager).  By passing the handle to the ClientManager using 
+            ClientModule initiated registration, modules dependent on the 
+            ClientManager service need not raise cyclic dependency errors.  
+            Regardless cyclic references exists but because the Serviceable 
+            interface is not used to grab the handle containers don't choke.  
+            This is why the InputManager, OutputManager and the ProtocolEngine 
+            interfaces extend the ClientManagerSlave interface.  On 
+            initialization the ClientManager registers itself with the 
+            ClientManagerSlaves so they need not lookup the ClientManager within
+            the service lifecycle method.
+        </para>
+        
+        <para>
+            <ulink url="images/ModuleDependencies.gif">Figure II</ulink>
+            is a component
+            diagram which depicts the service interfaces and the modules that
+            implement them.  The components are modules that have a solid 
+            supporting link to a circular service interface node.  Note that
+            the modules are service interface implementations and they have 
+            directed dotted line dependencies on the service interfaces 
+            supported by other modules.  Modules never directly depend on other
+            modules, nor should they ever!  
+        </para>
+    </section>
+    
+    <section>
+        <title>Conclusion</title>
+        <para>
+            Our goals in this article were to introduce the fundimental modular
+            architecture of the server.  We want readers to be able to 
+            comprehend how server modules are defined according to the Avalon
+            Framework APIs.  Readers should therefore understand what a module 
+            is as a Avalon Component and which service interface is supported
+            by each critical server module.  We would also like readers to step 
+            away with a rough understanding of the SEDA stages within the server
+            and to be able to differentiate between simple modules, stages and 
+            those that fall under neither category.  Ultimately users should 
+            possess an understanding of module dependencies and their 
+            interactions within the processing pipeline for LDAP requests with 
+            the subsequent transmission of a response.
+        </para>
+    </section>
+    
+</article>

Added: incubator/directory/eve/branches/start/src/docbook/design/triggers-and-procedures.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/docbook/design/triggers-and-procedures.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,121 @@
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V4.1.2.5//EN"
+    "http://www.oasis-open.org/docbook/xml/simple/4.1.2.5/sdocbook.dtd">
+
+
+<article>
+<title>Triggers and Stored Procedures</title>
+
+<para>
+    All of us that have had serious experience using a traditional RDBMS are more
+    than familiar with the use of triggers and stored procedures.  Triggers and
+    stored procedures provide the basic framework for a rich application development
+    platform.  We agree with most architects when we reject the idea of using the
+    integration teir for the development of whole applications.  However it is a
+    place where peices specific to the integration teir can be developed as 
+    components in the overall application.  Sometimes there is no way to avoid 
+    using these component even though they can be ignored for the majority of 
+    applications.  In this way, triggers and stored procedures are a nice feature
+    to have in any data management system if the need requires them.
+</para>
+
+<para>
+    Triggers and stored procedures have played a major role in the database world.
+    Why not enable the facility within the world of the directory?  Directories unlike
+    databases have until recently been a nacent and uncommon technology.  In total 
+    LDAP has existed for less than two decades.  The demand for LDAP is just now 
+    catching on as directories become a staple component in the architect's palette.  
+    The idea of architecting for the constant shared data in a system as well as the 
+    ever changing data is finally manifesting itself.  As applications using directory
+    services increase so do the potential for circumstances requiring the use of 
+    triggers.  Just recently the some effort have begun to incorporate triggers into
+    the LDAP specification as an extention.  The LTAP (Lightweigth Trigger Access 
+    Process) http://ltap.bell-labs.com/ is one step in that direction but it implements
+    LDAP triggers using a gateway process blanketed over an existing directory.  Ldapd
+    incorporates such functionality directly into the server.
+</para>
+
+<para>
+    This chapter explores an experimental trigger and stored procedure subsystem 
+    within the ldapd server.  The LDAP tigger and stored procedure counterparts 
+    are not all that different from those in the world of databases.  The idea is 
+    essentially the same.  A trigger defines the conditions required to fire.  
+    Firing a trigger invokes a stored procedure or an embedded procedure specified 
+    as the body of the trigger.  Hence like a business rule a trigger has a LHS 
+    specifying the conditions for firing it and a RHS specifying the actions to take 
+    when fired.  Our goals are to describe how these subsystems have been designed, 
+    and implemented in ldapd. Consequently we will show how triggers can be specified, 
+    and enabled within a directory information tree served by ldapd.
+</para>
+
+<section>
+    <title>
+        UseCases and Conventions
+    </title>
+    
+    <para>
+        some text here.
+    </para>
+
+    <para>
+        SOME NOTES ON TRIGGERS
+        
+        Triggers are going to need some sort of trigger specification.  This spec
+        must describe whether trigger itself is relicated and whether or not the
+        resultant changes induced by the trigger are replicated.  Conversely we
+        may descide to put these parameters into a stored procedure spec instead
+        that way a timer driven firing of a stored proc may suppress replication.
+        
+        If a trigger itself is replicated then it cannot replicate the effects of
+        the opperation because then the operations would be executed twice on the
+        replicas.  Once by the operation of the replicated trigger, and again by
+        the replicated events fired as the result of the trigger firing on the
+        master. So a trigger is either replicated and does not replicate resultant
+        change driven events or is not replicated and does replicate the resultant
+        events caused by the stored procedures it executes.
+        
+        Sometime there are scenarios when one scheme will be better than the other.
+        For example an involved CPU intensive procedure that updates only one entry
+        like a time triggered summary job may be better off kept on the master without
+        replicating the trigger and only replicating the events triggered by the
+        execution of its stored procedure.  This way the expensive operations is
+        run once and its results are replicated rather than running the operation
+        on every replica.  Conversely if the trigger's execution results in a large
+        number of changes then it may be best to replicate the trigger and not its
+        results because the amount of network communication required may be
+        detrimental.
+    </para>
+        <programlisting>
+            trigger   : CREATE TRIGGER NAME 
+                OWNED BY dn [ ON USERS dn+ ] [ AS dn ] when ENTITY matches DO procedure ;
+            when      : WHEN ( BEFORE | AFTER | FAILED ) 
+                ( ADD | DELETE | MODIFY | READ | BIND | UNBIND )+ ;
+            matches   : MATCHES dn '?' [ scope ] '?' [ filter ] '?' [ FIELDS attribName+ ] ;
+            procedure : NAME | LANG ( JAVA | JYTHON ) '{' code '}' ;
+            
+            
+            attributetype ( UNDEFINED_OID
+                NAME 'op'
+                DESC 'An LDAP Operation'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+            objectclass ( UNDEFINED_OID
+                NAME 'trigger'
+                DESC 'LDAP trigger'
+                SUP top
+                MAY ( run-as $  )
+                MUST ( uid $ owner $ op $ when $ match $ procedure ) 
+            )
+
+            LDAPv2 (RFC 1777) and LDAPv3 (RFCs 2251 through 2256) compliant, including support for 
+            extensible schema, referrals, paged results, and change log extensions 
+
+            Dynamically computed virtual attributes for integration with other information sources 
+        </programlisting>
+    <para>
+        
+    
+    </para>
+</section>
+
+</article>

Added: incubator/directory/eve/branches/start/src/images/AddRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/AdminSchemaContext.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/BackendInterfaces.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/BindRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/CRUDLifecycle.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/CompareRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/DelRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ExtendedRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/InputEventHandlerHandleEvent.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/InputModuleRegister.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ListenerModuleRun.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ModifyDNRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ModifyRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ModuleDependencies.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/OutputEventHandlerHandleEvent.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/OutputModuleWrite.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ReqRespStageFlow.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/RequestEventHandlerHandleEvent.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/ResponseEventHandlerHandleEvent.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/SearchRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/images/UnBindRequestProcessorProcess.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/AbstractModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/AbstractModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,123 @@
+/*
+ * $Id: AbstractModule.java,v 1.2 2003/03/13 18:26:29 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+
+
+/**
+ * Abstract module class provided for convenience.  Provides start, stop and
+ * logger methods out of the box.  Subclasses that override start and stop must
+ * call start() and stop() super class methods after performing their required
+ * opertations in the respective override.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public abstract class AbstractModule
+    implements Module
+{
+    /** The logger used by this LogEnabled module. */
+    private Logger m_logger = null ;
+    /** Member used to track whether or not this module has been started. */
+    private boolean m_hasStarted = false ;
+
+
+
+	public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+    }
+
+
+	public void initialize()
+        throws Exception
+    {
+    }
+
+
+    /**
+     * Starts this module.  All subclasses much call this super method after
+     * performing their own start tasks.
+     *
+     * @throws Exception of any kind subclasses of which would depend on the
+     * nature of derived concrete modules.
+     */
+    public void start()
+        throws Exception
+    {
+        m_hasStarted = true ;
+    }
+
+
+    /**
+     * Stops this module.  All subclasses much call this super method after
+     * performing their own stop tasks.
+     * 
+     * @throws Exception of any kind subclasses of which would depend on the
+     * nature of derived concrete modules.
+     */
+    public void stop()
+        throws Exception
+    {
+        m_hasStarted = false ;
+    }
+
+
+    /**
+     * Checks to see if this module has started.
+     *
+     * @return true if it has started, false otherwise.
+     */
+    public final boolean hasStarted()
+    {
+        return m_hasStarted ;
+    }
+
+
+    /**
+     * Gets the Logger used by this module to log messages.
+     *
+     * @return this modules Logger.
+     */
+    public final Logger getLogger()
+    {
+        return m_logger ;
+    }
+
+
+    /**
+     * LogEnabled interface implementation which sets this Modules or LogEnabled
+     * class' Logger.
+     *
+     * @param a_logger used by this LogEnabled module.
+     */
+    public void enableLogging(Logger a_logger)
+    {
+        m_logger = a_logger ;
+    }
+
+
+    public void contextualize(Context a_context)
+        throws ContextException
+    {
+        if(getLogger().isDebugEnabled()) {
+        	getLogger().debug(this.getImplementationName() +
+                " executing contextualize phase") ;
+        }
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/Kernel.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/Kernel.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,63 @@
+/*
+ * $Id: Kernel.java,v 1.4 2003/08/22 21:15:54 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve ;
+
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.service.ServiceManager ;
+
+
+/**
+ * Some very primitive functionality to a kernel used to fire up the server or
+ * just parts of it.
+ */
+public interface Kernel
+{
+    /**
+     * Gets path to the root directory where the sar has been unraveled.
+     */
+    String getRoot() ;
+
+    /**
+     * Sets the root directory where the sar has been unraveled.  Must be set
+     * before bootstraping.
+     */
+    void setRoot( String a_rootDirPath ) ;
+
+    /**
+     * Starts up the kernel starting a single module and all modules it depends
+     * on.  Using this configuration backend subsystems alone can be started
+     * without firing up the entire server.
+     */
+    void bootStrap( String a_module ) throws Exception ;
+
+    /**
+     * Starts up the entire server with all the modules.
+     */
+    void bootStrap() throws Exception ;
+
+    void shutdown() ;
+
+    /**
+     * Gets the service manager used by components to resolve dependent
+     * services exposed by server plugins.
+     */
+    ServiceManager getServiceManager() ;
+
+    /**
+     * Gets the system logger for this Kernel
+     */
+    Logger getLogger() ;
+
+    /**
+     * Gets the component logger for a module in this Kernel.
+     */
+    Logger getLogger( String a_module ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/Module.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/Module.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,81 @@
+/*
+ * $Id: Module.java,v 1.4 2003/08/22 21:15:54 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve ;
+
+import org.apache.avalon.framework.activity.Startable ;
+import org.apache.avalon.framework.thread.ThreadSafe ;
+import org.apache.avalon.framework.logger.LogEnabled ;
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.configuration.Configurable ;
+import org.apache.avalon.framework.service.Serviceable ;
+import org.apache.avalon.framework.activity.Initializable ;
+import org.apache.avalon.framework.context.Contextualizable ;
+
+
+/**
+ * Modules are pluggable black box components that can be started and stopped
+ * and are responsible for their own error handling and logging.  Some types of
+ * modules within ldapd are backend modules and replication modules.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public interface Module
+    extends
+    Startable,
+    ThreadSafe,
+    LogEnabled,
+    Serviceable,
+    Configurable,
+    Contextualizable,
+	Initializable
+{
+    /**
+     * Gets the service interface name of this module.
+     *
+     * @return the role of this module's implemented service.
+     */
+    String getImplementationRole() ;
+
+    /**
+     * Gets the name of the implementation.  For example the name of the
+     * Berkeley DB Backend module is "Berkeley DB Backend".
+     *
+     * @return String representing the module implementation type name.
+     */
+	String getImplementationName() ;
+
+    /**
+     * Gets the name of the implementation class.  For example the name of the
+     * Berkeley DB Backend implementation class is <code>
+     * "ldapdd.backend.berkeley.BackendBDb" </code>.
+     *
+     * @return String representing the module implementation's class name.
+     */
+    String getImplementationClassName() ;
+
+
+    /**
+     * Checks to see if this module has already started.
+     *
+     * @return true if the module started, false otherwise.
+     */
+    boolean hasStarted() ;
+
+    /**
+     * Gets the logger used by this module to log messages.
+     *
+     * @return the logger used by this module.
+     */
+    Logger getLogger() ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AtomicBackend.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AtomicBackend.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,40 @@
+/*
+ * $Id: AtomicBackend.java,v 1.5 2003/08/22 21:15:54 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import javax.naming.Name ; 
+import org.apache.eve.schema.Schema ;
+
+
+/**
+ * Atomic backends represent a concrete configurable Directory Information Base
+ *(DIB). They are not composed of other Backends.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.5 $
+ */
+public interface AtomicBackend
+    extends Backend, BackendConfig
+{
+    /**
+     * Role of this service interface as mandated by the avalon framework.
+     */
+    public static final String ROLE = AtomicBackend.class.getName() ;
+
+    /**
+     * Gets the normalized DN of the suffix managed by this AtomicBackend.
+     *
+     * @return Name representing the normalized root suffix for this
+     * AtomicBackend.
+     */
+    Name getSuffix() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributeAdapter.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributeAdapter.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,198 @@
+/*
+ * $Id: AttributeAdapter.java,v 1.3 2003/04/09 15:51:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Vector ;
+import java.util.Iterator ;
+import java.util.ArrayList ;
+import java.util.Collection ;
+
+import javax.naming.NamingException ;
+import org.apache.ldap.common.NotImplementedException ;
+import javax.naming.NamingEnumeration ;
+import javax.naming.directory.Attribute ;
+import javax.naming.directory.DirContext ;
+
+
+/**
+ * Attribute adapter which is a simple wrapper around a Collection.
+ */
+public class AttributeAdapter
+    implements Attribute
+{
+	Collection m_collection ;
+	String m_id ;
+
+
+	public AttributeAdapter(Collection a_collection, String a_id) {
+		m_id = a_id ;
+		m_collection = a_collection ;
+	}
+
+
+	public NamingEnumeration getAll() throws NamingException
+	{
+		final Iterator l_list = m_collection.iterator() ;
+		return new NamingEnumeration() {
+			public boolean hasMore() { return l_list.hasNext() ; }
+			public boolean hasMoreElements() { return l_list.hasNext() ; }
+			public Object nextElement() { return l_list.next() ; }
+			public Object next() { return l_list.next() ; }
+			public void close() {}
+		} ;
+	}
+
+
+	public Object get() throws NamingException
+	{
+		if(m_collection instanceof ArrayList) {
+			ArrayList l_al = (ArrayList) m_collection ;
+			if(l_al.size() > 0) {
+				return l_al.get(0) ;
+			} else {
+				return null ;
+			}
+		}
+
+		throw new NotImplementedException() ;
+	}
+
+
+	public int size()
+	{
+		return m_collection.size() ;
+	}
+
+
+	public String getID()
+	{
+		return m_id ;
+	}
+
+
+	public boolean contains(Object attrVal)
+	{
+		return m_collection.contains(attrVal) ;
+	}
+
+
+	public boolean add(Object attrVal)
+	{
+		if(m_collection.contains(attrVal)) {
+			return false ;
+		} else {
+			m_collection.add(attrVal) ;
+			return true ;
+		}
+	}
+
+
+	public boolean remove(Object attrval)
+	{
+		return m_collection.remove(attrval) ;
+	}
+
+
+	public void clear()
+	{
+		m_collection.clear() ;
+	}
+
+
+	public DirContext getAttributeSyntaxDefinition() throws NamingException
+	{
+		throw new UnsupportedOperationException(
+			"AttributeAdapter does not support schema info right now.") ;
+	}
+
+
+	public DirContext getAttributeDefinition() throws NamingException
+	{
+		throw new UnsupportedOperationException(
+			"AttributeAdapter does not support schema info right now.") ;
+	}
+
+
+	public Object clone() {
+		throw new UnsupportedOperationException(
+			"AttributeAdapter for event delivery does not support clone().") ;
+	}
+
+	//----------- Methods to support ordered multivalued attributes
+
+	public boolean isOrdered()
+	{
+		if(m_collection instanceof Vector ||
+		   m_collection instanceof ArrayList) {
+			return true ;
+		}
+
+		return false ;
+	}
+
+
+	public Object get(int ix) throws NamingException
+	{
+		if(m_collection instanceof ArrayList) {
+			return ((ArrayList) m_collection).get(ix) ;
+		} else if(m_collection instanceof Vector) {
+			return ((Vector) m_collection).get(ix) ;
+		}
+
+		throw new UnsupportedOperationException(
+			"Collection of " + m_collection.getClass().getName()
+			+ "does not support ordered access to attribute values") ;
+	}
+
+
+	public Object remove(int ix)
+	{
+		if(m_collection instanceof ArrayList) {
+			return ((ArrayList) m_collection).remove(ix) ;
+		} else if(m_collection instanceof Vector) {
+			return ((Vector) m_collection).remove(ix) ;
+		}
+
+		throw new UnsupportedOperationException(
+			"Collection of " + m_collection.getClass().getName()
+			+ "does not support ordered removal of attribute values") ;
+	}
+
+
+	public void add(int ix, Object attrVal)
+	{
+		if(m_collection instanceof ArrayList) {
+			((ArrayList) m_collection).add(ix, attrVal) ;
+			return ;
+		} else if(m_collection instanceof Vector) {
+			((Vector) m_collection).add(ix, attrVal) ;
+			return ;
+		}
+
+		throw new UnsupportedOperationException(
+			"Collection of " + m_collection.getClass().getName()
+			+ "does not support ordered addition to attribute values") ;
+	}
+
+
+	public Object set(int ix, Object attrVal)
+	{
+		if(m_collection instanceof ArrayList) {
+			return ((ArrayList) m_collection).set(ix, attrVal) ;
+		} else if(m_collection instanceof Vector) {
+			return ((Vector) m_collection).set(ix, attrVal) ;
+		}
+
+		throw new UnsupportedOperationException(
+			"Collection of " + m_collection.getClass().getName()
+			+ "does not support ordered alteration of attribute values") ;
+	}
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributesAdapter.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/AttributesAdapter.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,236 @@
+/*
+ * $Id: AttributesAdapter.java,v 1.4 2003/04/09 15:51:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Vector ;
+import java.util.Iterator ;
+import java.util.ArrayList ;
+import java.util.Collection ;
+
+
+import javax.naming.NamingException ;
+import javax.naming.NamingEnumeration ;
+import javax.naming.directory.Attribute ;
+import javax.naming.directory.DirContext ;
+import javax.naming.directory.Attributes ;
+
+import org.apache.ldap.common.NotImplementedException ;
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/**
+ * An Attributes interface adapter around an LdapEntry.
+ */
+public class AttributesAdapter
+    implements Attributes
+{
+	private final LdapEntry m_entry ;
+
+
+    public AttributesAdapter(LdapEntry a_entry) {
+        m_entry = a_entry ;
+    }
+
+
+    /**
+      * Determines whether the attribute set ignores the case of
+      * attribute identifiers when retrieving or adding attributes.
+      * @return true if case is ignored; false otherwise.
+      */
+    public boolean isCaseIgnored()
+    {
+        return true ;
+    }
+
+
+    /**
+      * Retrieves the number of attributes in the attribute set.
+      *
+      * @return The nonnegative number of attributes in this attribute set.
+      */
+    public int size()
+    {
+        return m_entry.attributes().size() ;
+    }
+
+    /**
+      * Retrieves the attribute with the given attribute id from the
+      * attribute set.
+      *
+      * @param attrID The non-null id of the attribute to retrieve.
+      * 	  If this attribute set ignores the character
+      *		  case of its attribute ids, the case of attrID
+      *		  is ignored.
+      * @return The attribute identified by attrID; null if not found.
+      * @see #put
+      * @see #remove
+      */
+    public Attribute get(String attrId)
+    {
+        if(m_entry.hasAttribute(attrId)) {
+	        return new AttributeAdapter(m_entry.getMultiValue(attrId), attrId) ;
+        }
+
+        return null ;
+    }
+
+
+    /**
+      * Retrieves an enumeration of the attributes in the attribute set.
+      * The effects of updates to this attribute set on this enumeration
+      * are undefined.
+      *
+      * @return A non-null enumeration of the attributes in this attribute set.
+      *		Each element of the enumeration is of class <tt>Attribute</tt>.
+      * 	If attribute set has zero attributes, an empty enumeration 
+      * 	is returned.
+      */
+    public NamingEnumeration getAll()
+    {
+        final Iterator l_list = m_entry.attributes().iterator() ;
+		return new NamingEnumeration() {
+			public boolean hasMore() { return l_list.hasNext() ; }
+			public boolean hasMoreElements() { return l_list.hasNext() ; }
+			public Object nextElement()
+            {
+                String l_attrId = (String) l_list.next() ;
+                Attribute l_attr = new AttributeAdapter(
+                    m_entry.getMultiValue(l_attrId), l_attrId) ;
+                return l_attr ;
+            }
+			public Object next()
+            {
+                String l_attrId = (String) l_list.next() ;
+                Attribute l_attr = new AttributeAdapter(
+                    m_entry.getMultiValue(l_attrId), l_attrId) ;
+                return l_attr ;
+            }
+			public void close() {}
+		} ;
+    }
+
+
+    /**
+      * Retrieves an enumeration of the ids of the attributes in the
+      * attribute set.
+      * The effects of updates to this attribute set on this enumeration
+      * are undefined.
+      *
+      * @return A non-null enumeration of the attributes' ids in
+      * 	this attribute set. Each element of the enumeration is
+      *		of class String.
+      * 	If attribute set has zero attributes, an empty enumeration 
+      * 	is returned.
+      */
+    public NamingEnumeration getIDs()
+    {
+        final Iterator l_list = m_entry.attributes().iterator() ;
+		return new NamingEnumeration() {
+			public boolean hasMore() { return l_list.hasNext() ; }
+			public boolean hasMoreElements() { return l_list.hasNext() ; }
+			public Object nextElement() { return l_list.next() ; }
+			public Object next() { return l_list.next() ; }
+			public void close() {}
+		} ;
+    }
+
+
+    /**
+      * Adds a new attribute to the attribute set.
+      *
+      * @param attrID 	non-null The id of the attribute to add.
+      * 	  If the attribute set ignores the character
+      *		  case of its attribute ids, the case of attrID
+      *		  is ignored.
+      * @param val	The possibly null value of the attribute to add.
+      *			If null, the attribute does not have any values.
+      * @return The Attribute with attrID that was previous in this attribute set;
+      * 	null if no such attribute existed.
+      * @see #remove
+      */
+    public Attribute put(String attrID, Object val)
+    {
+        try {
+        	m_entry.addValue(attrID, val) ;
+        } catch(NamingException e) {
+            throw new CascadingRuntimeException("Naming exception thrown", e) ;
+        }
+
+        return new AttributeAdapter(m_entry.getMultiValue(attrID), attrID) ;
+    }
+
+
+    /**
+      * Adds a new attribute to the attribute set.
+      *
+      * @param attr 	The non-null attribute to add.
+      * 		If the attribute set ignores the character
+      *		  	case of its attribute ids, the case of
+      * 		attr's identifier is ignored.
+      * @return The Attribute with the same ID as attr that was previous 
+      * 	in this attribute set;
+      * 	null if no such attribute existed.
+      * @see #remove
+      */
+    public Attribute put(Attribute attr)
+    {
+        try {
+			NamingEnumeration l_list = attr.getAll() ;
+			while(l_list.hasMore()) {
+				m_entry.addValue(attr.getID(), l_list.next()) ;
+			}
+	
+			return new AttributeAdapter(m_entry.getMultiValue(attr.getID()),
+				attr.getID());
+        } catch(NamingException e) {
+            throw new CascadingRuntimeException("Naming exception thrown", e) ;
+        }
+    }
+
+
+    /**
+      * Removes the attribute with the attribute id 'attrID' from
+      * the attribute set. If the attribute does not exist, ignore.
+      *
+      * @param attrID 	The non-null id of the attribute to remove.
+      * 		If the attribute set ignores the character
+      *		  	case of its attribute ids, the case of 
+      *               	attrID is ignored.
+      * @return The Attribute with the same ID as attrID that was previous 
+      * 	in the attribute set;
+      * 	null if no such attribute existed.
+      */
+    public Attribute remove(String attrId)
+    {
+        try {
+			Attribute l_attr =
+				new AttributeAdapter(m_entry.getMultiValue(attrId), attrId) ;
+			m_entry.removeValues(attrId) ;
+			return l_attr ;
+        } catch(NamingException e) {
+            throw new CascadingRuntimeException("Naming exception thrown", e) ;
+        }
+    }
+
+
+    /**
+      * Makes a copy of the attribute set.
+      * The new set contains the same attributes as the original set:
+      * the attributes are not themselves cloned.
+      *
+      * @return A non-null copy of this attribute set.
+      */
+    public Object clone() {
+        throw new UnsupportedOperationException(
+            "AttributesAdapter for event delivery does not allow clone ops.") ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Backend.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Backend.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,375 @@
+/*
+ * $Id: Backend.java,v 1.9 2003/03/27 16:30:37 jmachols Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.directory.DirContext ;
+import javax.naming.directory.SearchControls ;
+
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.eve.client.ClientManagerSlave ;
+
+
+/**
+ * Backend modules store entries in a manner specific to a backing store.
+ * 
+ * Backends may be memory resident non persistant stores, use flat files, xml,
+ * relational databases, non relational databases, or even other surrogate LDAP
+ * directories to store entries in whatever scheme they see fit. No limitations
+ * are placed on how Backends store or manage entries.
+ *
+ * These interfaces simply define a means to get to Entry attributes in a
+ * standard way.  Hence this interface establishes one of the primary contracts
+ * that the ldap server holds with a pluggable backend module.  Other
+ * complementary interfaces in this package are artifacts that are required to
+ * interface with a Backend or the attribute contents of entries.  Backend
+ * implementations must uphold these server-backend contracts.
+ *
+ * Related Documentation:
+ * <ul>
+ * <li><a href=backendhowto.html>HowTo Build A Backend</a></li>
+ * <li><a href=dnnormalization.html>Distinguished Name Normalization</a></li>
+ * <li><a href=contract.html>Server-Backend Contract.</a></li>
+ * <li><a href=http://afs.wu-wien.ac.at/manuals/rfc-ldap.html>
+ * Relevant LDAP RFCs</a></li></ul>
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: jmachols $
+ * @version $Revision: 1.9 $
+ */
+public interface Backend extends ClientManagerSlave
+{
+    /**
+     * Constant used to represent object level search scope which equals
+     * SearchControls.OBJECT_SCOPE.
+     */
+    int BASE_SCOPE = SearchControls.OBJECT_SCOPE ;
+    /**
+     * Constant used to represent single level search scope which equals
+     * SearchControls.ONELEVEL_SCOPE.
+     */
+    int SINGLE_SCOPE = SearchControls.ONELEVEL_SCOPE ;
+    /**
+     * Constant used to represent subtree level search scope which equals
+     * SearchControls.SUBTREE_SCOPE.
+     */
+    int SUBTREE_SCOPE = SearchControls.SUBTREE_SCOPE ;
+
+    /** Constant used to represent attribute/value addition. */
+    int ADD_ATTRIBUTE = DirContext.ADD_ATTRIBUTE ;
+    /** Constant used to represent attribute/value removal. */
+    int REMOVE_ATTRIBUTE = DirContext.REMOVE_ATTRIBUTE ;
+    /** Constant used to represent attribute/value replacement. */
+    int REPLACE_ATTRIBUTE = DirContext.REPLACE_ATTRIBUTE ;
+
+
+    ///////////////////////////
+    // Entry CRUD Operations //
+    ///////////////////////////
+
+
+    /**
+     * Creates a new Entry without adding it to the database.  The entry is
+     * invalid until it is added to the instantiating backend via a create()
+     * call. The new Entry contains a single operational attribute: the DN of
+     * the Entry in the case and format specified by the user.  Hence calls to
+     * the <code>getEntryDN()</code> method of the Entry shall return the DN
+     * argument to this method.  Calls to the <code>getNormalizedDN()</code>
+     * method will return the normalized DN.
+     * 
+     * To comply with the server backend contract the DN argument must not be
+     * tampered with by a normalizer.  This method expects a_dn to be the
+     * original user provided unformatted DN.
+     *
+     * @param a_dn the user provided distinguished name of the new Entry.
+     * @return the newly instantiated Entry to be added to this Backend via the
+     * create() method.
+     * @throws javax.naming.NameNotFoundException when a component of the parent cannot be
+     * resolved because it is not bound - the parent entry of the new Entry
+     * must be bound for this factory method.
+     * @throws javax.naming.InvalidNameException when a_dn is not syntactically correct.
+     * @throws javax.naming.NameAlreadyBoundException when an Entry with a_dn already
+     * exists.
+     * @throws BackendException when a backing store error occurs.
+     */
+    LdapEntry newEntry(String a_dn)
+        throws BackendException, NamingException ;
+
+    /**
+     * Deletes (cru<b>D</b>) an entry from the Backend and all cached
+     * referrences to it.  The Entry cache if any is purged of referrences to
+     * the Entry.
+     *
+     * @param an_entry Entry to be deleted
+     * @throws BackendException when removal from the backend fails due to a
+     * backing store error, or an_entry is <b>NOT</b> valid, or is not managed
+     * by this Backend.
+     * @throws javax.naming.ContextNotEmptyException when non leaf entries are attempted to
+     * be deleted.
+     */
+    void delete(LdapEntry an_entry)
+        throws BackendException, NamingException ;
+
+    /**
+     * Creates (<b>C</b>rud) an Entry in this Backend.
+     *
+     * @param an_entry to put into this Backend.
+     * @throws BackendException if anything goes drastically wrong with this
+     * Backend while attempting to perform the operation, or if an Entry with
+     * the same DN already exists within this Backend, or if the Entry is not
+     * managed by this Backend.
+     * @throws javax.naming.directory.SchemaViolationException if the attributes supplied with an
+     * entry do not satisfy objectclass schema constraints.
+     * @throws javax.naming.NameAlreadyBoundException if an Entry with a_dn already exists,
+     * this would occur if another thread creates an Entry with its DN between
+     * the call to newEntry and this method.
+     * @throws javax.naming.directory.InvalidAttributesException when all the mandatory attributes
+     * required by the objectclasses of the object are not present.
+     */
+    void create(LdapEntry an_entry)
+        throws BackendException, NamingException ;
+
+
+    /**
+     * Read (c<b>R</b>ud) an Entry from this Backend based on it's unique DN.
+     *
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * @param a_dn the unique distinguished name of the entry to get.
+     * @return the entry identified by a_dn or null if one by that name does 
+     * not exist.
+     * @throws BackendException if anything goes drastically wrong with this
+     * Backend while attempting to perform the operation.
+     * @throws javax.naming.NameNotFoundException when a component of the name cannot be
+     * resolved because it is not bound.
+     * @throws javax.naming.InvalidNameException if a_dn is not syntactically correct.
+     */
+    LdapEntry read(Name a_dn)
+        throws BackendException, NamingException ;
+
+    /**
+     * Updates (cr<b>U</b>d) the valid Entry by presuming that it has been
+     * altered.  The alterations may effect multiple attributes by adding
+     * values, removing values or changing values.  The Entry must be valid
+     * for this operation to take place.
+     *
+     * @param an_entry Entry to modify
+     * @throws BackendException when the modification fails, or an_entry is not
+     * valid.
+     * @throws javax.naming.directory.SchemaViolationException if the attributes supplied with an
+     * entry do not satisfy objectclass schema constraints.
+     * @throws javax.naming.directory.InvalidAttributesException when all the mandatory attributes
+     * required by the objectclasses of the object are not present.
+     */
+    void update(LdapEntry an_entry)
+        throws BackendException, NamingException ;
+
+
+    //////////////////////////////////////
+    // Parent Child Relation Operations //
+    //////////////////////////////////////
+
+
+    /**
+     * Lists the children of an entry identified by a_dn.  The returned Cursor
+     * enumerates through the children.<br>
+     * <br>
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * @param a_parentDN the parent entry's distinguished name.
+     * @return a cursor enumerating over the child entries of the parent.
+     * @throws BackendException if anything goes drastically wrong with this
+     * Backend while attempting to perform the operation.
+     * @throws javax.naming.NameNotFoundException when a component of the name cannot be
+     * resolved because it is not bound.
+     * @throws javax.naming.InvalidNameException if a_parentDN is not syntactically correct.
+     */
+    Cursor listChildren(Name a_parentDN)
+        throws BackendException, NamingException ;
+
+    /**
+     * Gets the parent of a child entry.
+     * 
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * @param a_childDN the distinguished name of the child entry.
+     * @return the parent entry of an entry identified by a child DN or the
+     * child entry if the child is the suffix.
+     * @throws BackendException if anything goes drastically wrong with this
+     * Backend while attempting to perform the operation.
+     * @throws javax.naming.NameNotFoundException when a component of the name cannot be
+     * resolved because it is not bound.
+     * @throws javax.naming.InvalidNameException if a_childDN is not syntactically correct.
+     */
+    LdapEntry getParent(Name a_childDN)
+        throws BackendException, NamingException ;
+
+    /**
+     * Checks to see if an entry with a distinguished name exists within this
+     * Backend.
+     * 
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * @param a_dn the distinguished name of the entry to check for.
+     * @return true if the entry exists within this Backend instance.
+     * @throws BackendException if anything goes drastically wrong with this
+     * Backend while attempting to perform the operation.
+     * @throws javax.naming.InvalidNameException if a_dn is not syntactically correct.
+     */
+    boolean hasEntry(Name a_dn)
+        throws BackendException, NamingException ;
+
+
+    /**
+     * Tests to see if this entry is a/the suffix Entry of this Backend.
+     * Unified composite backends will return true if the Entry is a valid
+     * suffix within the set of Backends composing it.
+     *
+     * @param an_entry the Entry to test if it is the suffix of this Backend or one of
+     * its composing Backends if this Backend is a UnifiedBackend.
+     * @return true if the Entry's DN is equivalent to the DN of this Backend,
+     * or one contained by a UnifiedBackend, otherwise false.
+     */
+    boolean isSuffix(LdapEntry an_entry)
+        throws NamingException ;
+
+    /**
+     * Checks to see if a user dn is the dn of this backend or one of its
+     * AtomicBackends if it is a UnifiedBackend.
+     *
+     * @param a_userDn the user dn to check for.
+     * @return true if a_userDn represents an admin dn, false otherwise.
+     * @throws NamingException if their is a problem with the specified user dn.
+     */
+    boolean isAdminUser(Name a_userDn)
+        throws NamingException ;
+
+    ////////////////////////
+    // Special Operations //
+    ////////////////////////
+
+    /**
+     * Searches for candidate entries on the backend starting on a base DN 
+     * using a search filter with search controls.
+     * 
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * W O R K   I N   P R O G R E S S
+     *
+     * @param a_filter String representation of an LDAP search filter.
+     * @param a_baseDN String representing the base of the search.
+     * @param a_scope SearchControls governing how this search is to be
+     * conducted.
+     * @throws BackendException on Backend errors or when the operation cannot
+     * proceed due to a malformed search filter, a non-existant search base, or
+     * inconsistant search controls.
+     * @throws javax.naming.InvalidNameException if a_baseDN is not syntactically correct.
+     * @throws javax.naming.NameNotFoundException when a component of a_baseDN cannot be
+     * resolved because it is not bound.
+     * @throws javax.naming.directory.InvalidSearchFilterException when the specification of a search
+     * filter is invalid. The expression of the filter may be invalid, or there
+     * may be a problem with one of the parameters passed to the filter.
+     * @throws javax.naming.directory.InvalidSearchControlsException when the specification of the
+     * SearchControls for a search operation is invalid. For example, if the
+     * scope is set to a value other than OBJECT_SCOPE, ONELEVEL_SCOPE,
+     * SUBTREE_SCOPE, this exception is thrown.
+     */
+    Cursor search(ExprNode a_filter, Name a_baseDN, int a_scope)
+        throws BackendException, NamingException ;
+
+    /**
+     * Modifies the relative distinguished name (RDN) of an entry
+	 * without changing any parent child relationships.  This call
+	 * has the side effect of altering the distinguished name of
+	 * descendent entries if they exist.  The boolean argument will
+	 * optionally remove the existing RDN attribute value pair
+	 * replacing it with the new RDN attribute value pair.  If other
+	 * RDN attribute value pairs exist besides the current RDN they
+	 * will be spared.
+     *
+     * @param an_entry the entry whose RDN is to be modified.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    void modifyRdn(LdapEntry an_entry, Name a_newRdn, boolean a_deleteOldRdn)
+	    throws BackendException, NamingException ;
+
+    /**
+     * Moves a child entry without changing the RDN under a new parent
+     * entry.  This effects the parent child relationship between the
+     * parent entry and the child entry.  The index for the child
+     * mapping it to the current parent is destroyed and a new index
+     * mapping it to the new parent is created.  As a side effect the
+     * name of the child entry and all its descendants will reflect the
+     * move within the DIT to a new parent.  The old parent prefix to
+     * the distinguished names of the child and its descendents will be
+     * replaced by the new parent DN prefix.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    void move(LdapEntry a_parentEntry, LdapEntry a_childEntry)
+	    throws BackendException, NamingException ;
+
+    /**
+     * This overload combines the first two method operations into one.
+     * It changes the Rdn and the parent prefix at the same time while
+	 * recursing name changes to all descendants of the child entry. It
+	 * is obviously more complex than the other two operations alone and
+	 * involves changes to both parent child indices and DN indices.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    void move(LdapEntry a_parentEntry, LdapEntry a_childEntry,
+	    Name a_newRdn, boolean a_deleteOldRdn)
+	    throws BackendException, NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendConfig.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendConfig.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,119 @@
+/*
+ * $Id: BackendConfig.java,v 1.4 2003/03/13 18:26:41 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+import java.util.Iterator ;
+import javax.naming.InvalidNameException ;
+
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+import javax.naming.Name;
+
+
+/**
+ * Interface used to manage the configuration of an AtomicBackend.
+ */
+public interface BackendConfig
+{
+    /** The default entry cache size. */
+    int DEFAULT_ENTRY_CACHESZ = 1000 ;
+
+    /**
+     * Tests to see if the backend of this configuration is operating in read
+     * only mode.  If true alterations to the backend will result in
+     * ReadOnlyExceptions being thrown at runtime.
+     *
+     * @return true if the backend is in read only mode false otherwise.
+     */
+    boolean isReadOnly() ;
+
+    /**
+     * Sets the read only operational mode of a backend using this
+     * configuration.
+     *
+     * @param a_isReadOnlyMode true if backend is to be configured for read 
+     * only mode false otherwise.
+     */
+    void setReadOnly(boolean a_isReadOnlyMode) ;
+
+    /**
+     * Sets the maximum size the entry cache may grow to.
+     *
+     * @param a_numMaxEntries the maximum number of entries that can be held.
+     * @throws BackendException if the configurable module has started and is 
+     * not Reconfigurable.
+     */
+    void setEntryCacheSize(int a_numMaxEntries)
+        throws BackendException ;
+
+    /**
+     * Gets the absolute path to the working directory for the configurable 
+     * backend.
+     *
+     * @return the absolute working directory path.
+     */
+    String getWorkingDirPath() ;
+
+    /**
+     * Sets the working directory path for implementation specific files or 
+     * logs if any.
+     *
+     * @param a_dirPath the absolute path to the working directory for the 
+     * configurable backend.
+     * @throws BackendException if the configurable module has started and is 
+     * not Reconfigurable.
+     */
+    void setWorkingDirPath(String a_dirPath)
+        throws BackendException ;
+
+    /**
+     * Sets the password for the admin user for the configurable backend.
+     *
+     * @param an_adminDN the distinguished name of the backend admin.
+     * @throws InvalidNameException if an_adminDN does not conform to DN 
+     * syntax.
+     * @throws BackendException if the configurable module has started and is 
+     * not Reconfigurable.
+     * @throws InvalidNameException if an_adminDN not in correct DN syntax 
+     */
+    void setAdminUserDN(Name an_adminDN)
+        throws BackendException, InvalidNameException ;
+
+    /**
+     * Gets the admin user distinguished name for the configurable backend.
+     *
+     * @return the distinguished name of the admin user.
+     */
+    Name getAdminUserDN() ;
+
+    /**
+     * Sets the password for the admin user for the configurable backend.
+     *
+     * @param an_adminPassword the distinguished name of the backend admin.
+     * @throws BackendException if the configurable module has started and is 
+     * not Reconfigurable.
+     */
+    void setAdminUserPassword(String an_adminPassword)
+        throws BackendException ;
+
+    /**
+     * Gets the encrypted password of the user in base 64 encoded format.
+     *
+     * @return base64 encoded cypher.
+     */
+    String getAdminUserPassword() ;
+
+    /**
+     * Gets the maximum size the entry cache may grow to.
+     *
+     * @return the maximum number of entries that can be held.
+     */
+    int getEntryCacheSize() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,44 @@
+/*
+ * $Id: BackendException.java,v 1.2 2003/03/13 18:26:42 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+import org.apache.avalon.framework.CascadingException ;
+
+
+/**
+ * This exception is thrown when Error encountered on backend operation.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class BackendException
+    extends CascadingException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param a_message The message associated with the exception.
+     */
+    public BackendException(String a_message)
+    {
+        super(a_message) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message and an error.
+     * @param a_message The message associated with the exception.
+     */
+    public BackendException(String a_message, Throwable a_throwable)
+    {
+        super(a_message, a_throwable) ;
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/BackendModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,482 @@
+/*
+ * $Id: BackendModule.java,v 1.10 2003/08/22 21:15:54 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.client.ClientManager ;
+import org.apache.eve.schema.SchemaManager ;
+
+import java.io.File ;
+import java.util.Iterator ;
+import java.util.Collection ;
+import java.util.NoSuchElementException ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.InvalidNameException ;
+import javax.naming.NameNotFoundException ;
+
+import org.apache.commons.collections.LRUMap ;
+import org.apache.commons.collections.MultiMap ;
+import org.apache.commons.collections.MultiHashMap ;
+
+import org.apache.avalon.phoenix.BlockContext ;
+
+import org.apache.avalon.framework.context.Context ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.context.ContextException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+
+public abstract class BackendModule
+    extends AbstractModule
+    implements AtomicBackend
+{
+    //
+    // Configuration Variables
+	//
+
+    protected boolean m_isReadOnly = false ;
+    protected Name m_suffix = null ;
+	protected String m_wkdirPath = null ;
+    protected Name m_adminUser = null ;
+    protected String m_adminPassword = null ;
+    protected BlockContext m_context ;
+
+    protected UnifiedBackend m_nexus = null ;
+    protected ClientManager m_clientMan = null ;
+    protected SchemaManager m_schemaManager = null ;
+	protected Schema m_schema = null ;
+    protected LRUMap m_cache = new LRUMap(1000) ;
+	protected MultiMap m_suffixEntry = new MultiHashMap() ;
+
+
+    /**
+     * Gets the normalized suffix name of this BackendModule.  The name is the
+     * normalized name found in the configuration for the backend within the
+     * suffix tag.
+     *
+     * @return the normalized suffix name for this BackendModule
+     */
+    public Name getSuffix()
+    {
+        return m_suffix ;
+    }
+
+
+    public Schema getSchema()
+    {
+        return m_schema ;
+    }
+
+
+    public boolean isReadOnly()
+    {
+        return this.m_isReadOnly ;
+    }
+
+
+    public void setReadOnly(boolean a_isReadOnlyMode)
+    {
+        this.m_isReadOnly = a_isReadOnlyMode ;
+    }
+
+
+    public void setEntryCacheSize(int a_numMaxEntries)
+        throws BackendException
+    {
+        this.m_cache.setMaximumSize(a_numMaxEntries) ;
+    }
+
+
+    public String getWorkingDirPath()
+    {
+        return this.m_wkdirPath ;
+    }
+
+
+    /**
+     * Sets the working directory path for implementation specific files or logs
+     * if any.
+     *
+     * @param a_dirPath the absolute path to the working directory for the
+     * configurable backend
+     * @throws BackendException if the configurable module has started and is
+     * not Reconfigurable.
+     */
+    public void setWorkingDirPath(String a_dirPath)
+        throws BackendException
+    {
+        if (hasStarted()) {
+            throw new BackendException("Cannot change working directory path "
+                + "after backend has started!") ;
+        }
+
+        File l_dir = new File(a_dirPath) ;
+
+        if (!l_dir.exists()) {
+            throw new BackendException(a_dirPath + " does not exist") ;
+        } else if (!l_dir.canWrite()) {
+            throw new BackendException("Cannot read " + a_dirPath) ;
+        } else if (!l_dir.canWrite()) {
+            throw new BackendException("Cannot write to " + a_dirPath) ;
+        } else if (!l_dir.isDirectory()) {
+            throw new BackendException(a_dirPath + " is not a directory.") ;
+        }
+
+        this.m_wkdirPath = l_dir.getAbsolutePath() ;
+    }
+
+
+    public void setAdminUserDN(Name an_adminDN)
+        throws BackendException
+    {
+        this.m_adminUser = an_adminDN ;
+    }
+
+
+    public Name getAdminUserDN()
+    {
+        return m_adminUser ;
+    }
+
+
+    public void setAdminUserPassword(String an_adminPassword)
+        throws BackendException
+    {
+        this.m_adminPassword = an_adminPassword ;
+    }
+
+
+    public String getAdminUserPassword()
+    {
+        return this.m_adminPassword ;
+    }
+
+
+    public int getEntryCacheSize()
+    {
+        return this.m_cache.getMaximumSize() ;
+    }
+
+
+    public void initialize()
+        throws Exception
+    {
+        if(hasEntry(getSuffix())) {
+            getLogger().info("Suffix entry exists skipping initial creation!") ;
+            return ;
+        }
+
+		getLogger().info("Suffix entry DOES NOT EXIST! " +
+            "Creating Suffix entry for the first time.") ;
+
+        // Extract User Provided Distinguished Name and create the new suffix
+        // root entry.
+        Collection l_col = (Collection) m_suffixEntry.get(Schema.DN_ATTR) ;
+        if(l_col == null) {
+            l_col = (Collection) m_suffixEntry.get("dn") ;
+        }
+        if(l_col == null) {
+			throw new BackendException("Cannot find a 'distinguishedName' or "
+                + "'dn' attribute in the suffix entry!") ;
+        }
+        String l_updn = (String) l_col.iterator().next() ;
+
+        LdapEntry l_entry = newEntry(l_updn) ;
+        Iterator l_keys = m_suffixEntry.keySet().iterator() ;
+        while(l_keys.hasNext()) {
+			String l_key = (String) l_keys.next() ;
+            if(l_key.toLowerCase().trim().equals(Schema.DN_ATTR) ||
+               l_key.toLowerCase().trim().equals("dn"))
+            {
+                continue ;
+            }
+
+            Iterator l_values = ((Collection)
+                m_suffixEntry.get(l_key)).iterator() ;
+            while(l_values.hasNext()) {
+                l_entry.addValue(l_key, l_values.next()) ;
+            }
+        }
+
+        create(l_entry) ;
+    }
+
+
+    /**
+     * All derived modules should call super.service first.
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        m_schemaManager
+            = (SchemaManager) a_manager.lookup(SchemaManager.ROLE) ;
+        m_nexus = (UnifiedBackend) a_manager.lookup(UnifiedBackend.ROLE) ;
+    }
+
+
+    public void start()
+        throws Exception 
+    {
+        super.start() ;
+        m_nexus.register( this ) ;
+    }
+
+
+    public void stop()
+        throws Exception 
+    {
+        m_nexus.unregister( this ) ;
+        super.stop() ;
+    }
+
+
+    public void registerClientManager( ClientManager a_manager )
+    {
+        m_clientMan = a_manager ;
+    }
+
+
+    ////////////////////////////////////////////
+    // Configuration Interface Implementation //
+    ////////////////////////////////////////////
+
+
+    /** DN of backend suffix property tag. */
+	public static final String SUFFIX_NODE = "suffix" ;
+    /** Admin user dn property tag. */
+	public static final String ADMINDN_NODE = "adminUserDN" ;
+    /** Admin user password property tag. */
+	public static final String ADMINPW_NODE = "adminUserPassword" ;
+    /** Working directory path property tag. */
+	public static final String WDIR_NODE = "workingDirPath" ;
+    /** Entry cache size property tag. */
+	public static final String CACHESZ_NODE = "entryCacheSize" ;
+
+
+    /**
+     * Avalon Configurable interface implementation. Here's an example
+     * configuration:<br>
+     *   <config>
+     *		<backend>
+     * 			<!-- mandatory -->
+     *			<suffix>dc=domain,dc=com</suffix>
+     * 
+     * 			<!-- mandatory -->
+     *			<adminUserDN>cn=admin,dc=domain,dc=com</adminUserDN>
+     * 
+     * 			<!-- mandatory -->
+     *			<adminUserPassword>secret</adminUserPassword>
+     * 
+     * 			<!-- mandatory -->
+     *			<workingDirPath>var/backend0</workingDirPath>
+     * 
+     * 			<!-- optional -->
+     *			<entryCacheSize>100</entryCacheSize>
+     *		</backend>
+     *   </config>
+     *
+     * @param a_config an avalon configuration object for this backend block.
+     * @throws ConfigurationException if the configuration is not correct.
+     */
+    public void configure( Configuration a_config )
+        throws ConfigurationException
+    {
+        Configuration l_suffixConfig = a_config.getChild( SUFFIX_NODE, false ) ;
+        if( l_suffixConfig == null )
+        {
+            throw new ConfigurationException( "Encountered module config with "
+                + "missing <" + SUFFIX_NODE+ "> tag! Cannot process "
+                + "config without unique backend suffix name." ) ;
+        }
+
+        // Got through all the attributes and add it to the suffix multimap
+        Configuration [] l_attributes = l_suffixConfig.getChildren() ;
+        for( int ii = 0 ; ii < l_attributes.length ; ii++ )
+        {
+            String l_name = l_attributes[ii].getAttribute( "name", null ) ;
+            String l_value = l_attributes[ii].getAttribute( "value", null ) ;
+
+            if( getLogger().isDebugEnabled() )
+            {
+                getLogger().debug( "Adding suffix attribute " + l_name
+                    + " with value " + l_value ) ;
+            }
+
+            m_suffixEntry.put( l_name, l_value ) ;
+        }
+
+		if( getLogger().isDebugEnabled() )
+        {
+            getLogger().debug( "Dumping suffix entry:\n" + m_suffixEntry ) ;
+        }
+
+        // Check multimap for the long and short names of 'dn' and complain if
+        // this or 'distinguishedName' keys do not exist.
+        Collection l_dnVals = ( Collection )
+            m_suffixEntry.get( Schema.DN_ATTR ) ;
+		if( l_dnVals == null )
+        {
+            l_dnVals = ( Collection ) m_suffixEntry.get( "dn" ) ;
+        }
+        if( l_dnVals == null )
+        {
+            throw new ConfigurationException( "Encountered module config with a"
+                + " missing attribute for the dn! Cannot process config without"
+                + " unique backend suffix distinguished name." ) ;
+        }
+
+        String l_suffix = null ;
+        try
+        {
+        	l_suffix = ( String ) l_dnVals.iterator().next() ;
+        }
+        catch( NoSuchElementException e )
+        {
+            throw new ConfigurationException( "Encountered module config with a"
+                + " missing value for the dn! Cannot process config without"
+                + " unique backend suffix distinguished name.") ;
+        }
+        if( l_suffix == null || l_suffix.trim().equals( "" ) )
+        {
+            throw new ConfigurationException("Encountered module config with a "
+                + "missing value for the dn! Cannot process config without "
+                + "unique backend suffix distinguished name.") ;
+        }
+
+
+        try
+        {
+            m_schema = m_schemaManager.getSchema( l_suffix ) ;
+
+            if( m_schema == null )
+            {
+                throw new ConfigurationException( "Got a null schema from the "
+                    + "schema manager using the suffix " + l_suffix ) ;
+            }
+            else if( getLogger().isDebugEnabled() )
+            {
+                getLogger().debug( "Got schema for suffix " + l_suffix ) ;
+            }
+
+            m_suffix = m_schema.getNormalizingParser().parse( l_suffix ) ;
+        }
+        catch( InvalidNameException e )
+        {
+            String l_msg = "The module suffix " + l_suffix
+                + " is not syntacticly correct: " ;
+            getLogger().error( l_msg, e ) ;
+            throw new ConfigurationException( l_msg, e ) ;
+        }
+        catch( NameNotFoundException e )
+        {
+            String l_msg = "Schema manager does not recognize this suffix: "
+                + l_suffix ;
+            getLogger().error( l_msg, e ) ;
+            throw new ConfigurationException( l_msg, e ) ;
+        }
+        catch( NamingException e )
+        {
+            String l_msg = "Schema manager does not recognize this suffix: "
+                + l_suffix ;
+            getLogger().error( l_msg, e ) ;
+            throw new ConfigurationException( l_msg, e ) ;
+        }
+
+
+        String l_adminUserDn =
+            a_config.getChild( ADMINDN_NODE ).getValue( null ) ;
+        if( l_adminUserDn == null )
+        {
+            throw new ConfigurationException( "Encountered "
+                + getImplementationName()
+                + " module config for suffix " + m_suffix + " with missing <"
+                + ADMINDN_NODE
+                + "> tag! Cannot process config without this mandatory tag." ) ;
+        }
+
+        try
+        {
+            m_adminUser =
+                m_schema.getNormalizingParser().parse( l_adminUserDn ) ;
+        }
+        catch( NamingException e )
+        {
+            throw new ConfigurationException( "Encountered "
+                + getImplementationName()
+                + " module config for suffix " + m_suffix + " with bad <"
+                + this.ADMINDN_NODE + "> tag! Cannot process config without "
+                + "this mandatory tag being present with a valid DN" ) ;
+        }
+
+		m_adminPassword = a_config.getChild( ADMINPW_NODE ).getValue( null ) ;
+        if( m_adminPassword == null )
+        {
+            throw new ConfigurationException( "Encountered "
+                + getImplementationName()
+                + " module config for suffix " + m_suffix + " with missing <"
+                + ADMINPW_NODE
+                + "> tag! Cannot process config without this mandatory tag." ) ;
+        }
+
+		m_wkdirPath = m_context.getBaseDirectory().getAbsolutePath()
+            + File.separator + a_config.getChild( WDIR_NODE ).getValue( null ) ;
+        File l_dir = new File( m_wkdirPath ) ;
+		if( ! l_dir.exists() )
+        {
+			l_dir.mkdirs() ;
+		}
+
+        if( m_wkdirPath == null )
+        {
+            throw new ConfigurationException( "Encountered "
+                + getImplementationName()
+                + " module config for suffix " + m_suffix + " with missing <"
+                + WDIR_NODE
+                + "> tag! Cannot process config without this mandatory tag." ) ;
+        }
+
+        m_cache.setMaximumSize( a_config.getChild( CACHESZ_NODE ).
+            getValueAsInteger( DEFAULT_ENTRY_CACHESZ ) ) ;
+    }
+
+
+    /**
+     * Looks up the BlockContext to get the base directory for the application.
+     */
+    public void contextualize( Context a_context )
+        throws ContextException
+    {
+        super.contextualize( a_context ) ;
+
+        try
+        {
+        	m_context = ( BlockContext ) a_context ;
+            if( getLogger().isDebugEnabled() )
+            {
+        		getLogger().debug( "Got handle on block context with base "
+                    + "directory "
+                    + m_context.getBaseDirectory().getAbsolutePath() ) ;
+            }
+        }
+        catch( ClassCastException e )
+        {
+			getLogger().debug( "Context is not an instance of BlockContext!" ) ;
+            throw new ContextException(
+                "Context is not an instance of BlockContext!", e ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Cursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/Cursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,424 @@
+/*
+ * $Id: Cursor.java,v 1.7 2003/03/13 18:26:44 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.ArrayList ;
+import java.util.Observable ;
+import java.util.Enumeration ;
+
+import javax.naming.NamingException ;
+import javax.naming.NamingEnumeration ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.logger.LogEnabled ;
+import java.util.Iterator;
+
+
+/**
+ * Cursors are automagically closing server-side NamingEnumerations.
+ * 
+ * Their open/closed state changes are comunicated to their Observers which
+ * are usually the backends that created them.
+ * <br><br>
+ * Backend implementors are required to have at least one concrete Cursor
+ * implementation. To do so requires the definition of three protected methods:
+ * <br>
+ * <br>
+ * <code> freeResources: </code>
+ * Cursors are potentially valuble resources to a backend and hence generally
+ * need to free up their own resources when exhausted.  The mechanism if any to
+ * free such resources will be specific to the backend's implementation. Cursor
+ * implementors are hence required to provide a protected <code>freeResources
+ * </code> method which is called whenever <code>close</code> is called on
+ * an open cursor.  Hence, <code>freeResources</code> can only be called once
+ * by calls to <code>close</code>.  The <code>freeResources</code>
+ * implementation should not make calls to the <code>close</code> method.
+ * Cursors automatically close themselves when they detect the consumption of
+ * all elements via calls to NamingEnumeration interfaces.
+ * <br><br>
+ * <code> advance</code>
+ * Backend failures need to propagate forward without breaking the Enumeration
+ * interface contract.  Unfortunately enumerations do not allow generic
+ * exception handling while getting the next element.  To work around this
+ * problem while also supporting NamingEnumeration methods, we require concrete
+ * cursor implementations to define an <code>advance</code> method
+ * implementation.  Rather than place iteration code within the
+ * <code>nextElement</code> implementation which is final and hence cannot be
+ * overridden by subclasses, implementors must use the protected <code>advance
+ * </code> method.  In fact, the <code>nextElement</code>
+ * implementation delegates calls to the <code>advance</code> method by
+ * wrapping the invokation with a BackendException/NamingException try catch
+ * which transduces the BackendExceptions and NamingExceptions into a subclass
+ * of NoSuchElementException (a.k.a a CursorException).
+ * <br><br>
+ * <code> canAdvance</code>
+ * Tests to see if this Cursor can advance will most likely be backend specific
+ * and may in some implementations throw a BackendException.  To facilitate the
+ * automatic close of cursors on list consumption and backend exceptions <code>
+ * hasMoreElement</code> has been defined as a final method that wraps calls
+ * to <code>canAdvance</code>.  Unlike the <code>advance</code> method
+ * backend exceptions are not transduced.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.7 $
+ * 
+ * @see CursorException
+ * @see NamingEnumeration
+ */
+public abstract class Cursor extends Observable
+        implements          				  // Cursors enumerate records
+            NamingEnumeration,                // Cursors can & should be closed
+            LogEnabled                        // Cursors can be enabled to log
+{
+    public static boolean debug = false ; 
+    /** Tracks this Cursors closed/open state. */
+    private boolean m_isClosed = false ;
+    /** Logger used by this Cursor */
+    private Logger m_logger = null ;
+    /** Cursor Listener List */
+    private ArrayList m_listeners = new ArrayList() ;
+
+
+    /////////////////////////////////////////
+    // LogEnabled Interface Implementation //
+    /////////////////////////////////////////
+
+
+    /**
+     * Sets the logger used by this Cursor which most probably will be set by
+     * its backend (factory).
+     *
+     * @param a_logger the logger to be used by this Cursor.
+     */
+    public void enableLogging(Logger a_logger)
+    {
+        m_logger = a_logger ;
+    }
+
+
+    /**
+     * Gets the logger used by this Cursor which most probably was inherited
+     * from its backend (factory).
+     *
+     * @return the logger used by this Cursor.
+     */
+    protected Logger getLogger()
+    {
+        return m_logger ;
+    }
+
+
+    ////////////////////////////////////////
+    // Closable Interface Implementations //
+    ////////////////////////////////////////
+
+
+    /**
+     * Gets whether this Cursor is currently open or closed.
+     *
+     * @return true if this Cursor is closed, otherwise false.
+     */
+    public final boolean isClosed()
+    {
+        return m_isClosed ;
+    }
+
+
+    /**
+     *
+     */
+    public final void close()
+        throws NamingException
+    {
+        if (!m_isClosed) {
+            m_isClosed = true ;
+            freeResources() ;
+            super.setChanged() ;
+        }
+    }
+
+
+    ///////////////////////////////////////////
+    // Enumeration Interface Implementations //
+    ///////////////////////////////////////////
+
+
+    /**
+     * Wrapper around advance which serves as an exception trap that transduces
+     * BackendExceptions into CursorExceptions (a subclass of the expected RT
+     * NoSuchElementException).
+     *
+     * @warning Invokations within the advance() implementations of subclasses
+     * will result in a never ending chain recursion.
+     * @return the next element in this Cursor.
+     * @side-effect Closes this cursor before throwing any exceptions.
+     */
+    public final Object nextElement()
+    {
+        if (m_isClosed) {
+            throw new CursorException("Cannot advance a closed cursor.") ;
+        }
+
+        Object l_element = null ;
+        try {
+            l_element = advance() ;
+
+            if (l_element == null) {
+                try {
+                    close() ;
+                } catch(NamingException ne) {
+					if( null != m_logger ) {
+						m_logger.error("Failed to close this cursor on null return"
+							+ " from advance():", ne) ;
+					}
+                }
+
+                throw new
+                    CursorException("Cursor advance returned null element!") ;
+            }
+
+            if(m_listeners.size() > 0) {
+                Iterator l_list = m_listeners.iterator() ;
+                CursorEvent l_event = new CursorEvent(this, l_element) ;
+
+                while(l_list.hasNext()) {
+                    CursorListener l_listener = (CursorListener) l_list.next() ;
+                    l_listener.cursorAdvanced(l_event) ;
+                }
+            }
+
+            return l_element ;
+        } catch (BackendException e) {
+			if( null != m_logger ) {
+				m_logger.error("Backing store errors resulted in cursor failure " +
+					"closing cursor:", e) ;
+			}
+
+            try {
+                close() ;
+            } catch(NamingException ne) {
+				if( null != m_logger ) {
+					m_logger.error("Failed to close this cursor on error:", ne) ;
+				}
+            }
+
+            throw new CursorException(e) ;
+        } catch (NamingException ne) {
+			if( null != m_logger ) {
+				m_logger.error("Failed on advance() closing cursor: ", ne) ;
+			}
+
+            try {
+                close() ;
+            } catch(NamingException ne2) {
+				if( null != m_logger ) {
+					m_logger.error("Failed to close this cursor on error:", ne2) ;
+				}
+            }
+
+            throw new CursorException(ne) ;
+        }
+    }
+
+
+    /**
+     * Wrapper around advance which serves as an exception trap that transduces
+     * BackendExceptions into CursorExceptions (a subclass of the expected RT
+     * NoSuchElementException).
+     *
+     * @warning Invokations within the advance() implementations of subclasses
+     * will result in a never ending chain recursion.
+     * @return the next element in this Cursor.
+     * @side-effect Closes this cursor before throwing any exceptions.
+     */
+    public final Object next()
+        throws NamingException
+    {
+        if (m_isClosed) {
+            throw new CursorException("Cannot advance a closed cursor.") ;
+        }
+
+        Object l_element = null ;
+        try {
+            l_element = advance() ;
+
+            if (l_element == null) {
+                close() ;
+                throw new
+                    CursorException("Cursor advance returned null element!") ;
+            }
+
+            return l_element ;
+        } catch (BackendException e) {
+			if( null != m_logger ) {
+				m_logger.error("Backing store errors resulted in cursor failure " +
+					"closing cursor:", e) ;
+			}
+            close() ;
+            throw new CursorException(e) ;
+        }
+    }
+
+
+    /**
+     * Wrapper around canAdvance which serves as means to close this Cursor 
+     * when the enumeration completes or an exception is encountered.
+     *
+     * @warning Invokations within the canAdvance implementations of subclasses
+     * will result in a never ending chain recursion.
+     * @return true if there exists a next element in this Cursor, else false
+     * @side-effect Closes this cursor if canAdvance() returns false or if it
+     * encounters a BackendException on the call to canAdvance().
+     */
+    public final boolean hasMoreElements()
+    {
+        if (m_isClosed) {
+            return false ;
+        }
+
+        try {
+            if (!canAdvance()) {
+                try {
+					if( null != m_logger ) {
+						if(m_logger.isDebugEnabled() && debug) {
+							m_logger.debug("Automagically closing exhausted "
+								+ "cursor.") ;
+						}
+                    }
+
+                    close() ;
+                } catch(NamingException ne) {
+					if( null != m_logger ) {
+						m_logger.error("Failed close upon exhausting cursor.", ne);
+					}
+                }
+
+                return false ;
+            }
+
+            return true ;
+        } catch (BackendException e) {
+			if( null != m_logger ) {
+				m_logger.error("Backend errors closing cursor prematurely", e) ;
+			}
+
+            try {
+                close() ;
+            } catch(NamingException ne) {
+				if( null != m_logger ) {
+					m_logger.error("Failed close upon backend error:", ne) ;
+				}
+            }
+
+            return false ;
+        } catch (NamingException e) {
+			if( null != m_logger ) {
+				m_logger.error("Naming errors closing cursor prematurely", e) ;
+			}
+
+            try {
+                close() ;
+            } catch(NamingException ne) {
+				if( null != m_logger ) {
+					m_logger.error("Failed close upon backend error:", ne) ;
+				}
+            }
+
+            return false ;
+        }
+    }
+
+
+    /**
+     * Wrapper around canAdvance which serves as a means to close this Cursor 
+     * when the enumeration completes or an exception is encountered.
+     *
+     * @warning Invokations within the canAdvance implementations of subclasses
+     * will result in a never ending chain recursion.
+     * @return true if there exists a next element in this Cursor, else false
+     * @side-effect Closes this cursor if canAdvance() returns false or if it
+     * encounters a BackendException on the call to canAdvance().
+     */
+    public final boolean hasMore()
+        throws NamingException
+    {
+        if (m_isClosed) {
+            return false ;
+        }
+
+        try {
+            if (!canAdvance()) {
+				if( null != m_logger ) {
+					if(m_logger.isDebugEnabled() && debug) {
+						m_logger.debug("Automagically closing exhausted cursor.") ;
+					}
+				}
+
+                close() ;
+                return false ;
+            }
+
+            return true ;
+        } catch (BackendException e) {
+			if( null != m_logger ) {
+				m_logger.error("Backend errors closing cursor prematurely", e) ;
+			}
+            close() ;
+            return false ;
+        }
+    }
+
+
+    //////////////////////
+    // Abstract Methods //
+    //////////////////////
+
+
+    /**
+     * Delagate method called by hasMore[Elements] to test if we can move
+     * forward.  Use this method to hold the code that would have normally gone
+     * into the hasMore[Elements] body. Unlike the hasMore[Elements] method the
+     * method allows the backend developer to throw backend specific exceptions
+     * which are eventually transduced into an automatic close of this Cursor.
+     * After closing this Cursor BackendExceptions are not rethrown as runtime
+     * exceptions to maintain [Naming]Enumeration semantics.
+     *
+     * @return true if Cursor can move to next non null entry, false otherwise.
+     * @throws BackendException when a error occurs on the entry backing store.
+     */
+    protected abstract boolean canAdvance()
+        throws BackendException, NamingException ;
+
+
+    /**
+     * Delagate method called by next[Element] to move this Cursor one element
+     * forward.  Use this method to hold the code that would have normally gone
+     * into the next[Element] body. Unlike the next[Element] method this method
+     * allows the backend developer to throw backend specific exceptions.
+     * BackendExceptions (which are not runtime exceptions) are transduced into
+     * CursorExceptions (which are runtime exceptions derived from
+     * NoSuchElementException).
+     *
+     * @return the element pointed to by this Cursor after advancing a step.
+     * @throws BackendException when a error occurs on the entry backing store.
+     */
+    protected abstract Object advance()
+        throws BackendException, NamingException ;
+
+
+    /**
+     * Called only once on cursor close to free up resources held by this
+     * Cursor.
+     */
+    protected abstract void freeResources() ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,39 @@
+/*
+ * $Id: CursorEvent.java,v 1.2 2003/03/13 18:26:47 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.EventObject;
+
+
+public class CursorEvent
+	extends EventObject
+{
+	public final Object element ;
+
+    CursorEvent(final Cursor a_cursor, final Object a_element)
+    {
+        super(a_cursor) ;
+
+        element = a_element ;
+    }
+
+
+    Cursor getCursorSource()
+    {
+        return (Cursor) this.source ;
+    }
+
+
+    Object getElement()
+    {
+        return element ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,73 @@
+/*
+ * $Id: CursorException.java,v 1.2 2003/03/13 18:26:49 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.NoSuchElementException ;
+
+
+/**
+ * This exception is thrown when Cursor has no more elements to return.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class CursorException
+    extends NoSuchElementException
+{
+    /** Nested exception if any. */
+    private final Throwable m_error ;
+
+
+    /**
+     * Constructs an Exception with a nested Throwable whose message is
+     * used to compose this exceptions message.
+     *
+     * @param an_exception a backend exception to wrap.
+     */
+    public CursorException(Throwable an_exception)
+    {
+        super(an_exception.toString()) ;
+        this.m_error = an_exception ;
+    }
+
+    /**
+     * Constructs an Exception without a message and without a Throwable.
+     */
+    public CursorException()
+    {
+        super() ;
+        this.m_error = null ;
+    }
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * 
+     * @param a_message The message associated with the exception.
+     */
+    public CursorException(String a_message)
+    {
+        super(a_message) ;
+        this.m_error = null ;
+    }
+
+
+    /**
+     * Checks to see if this exception was due to a backend/database error.
+     *
+     * @return true if a Throwable is wrapped by this exception or false
+     * otherwise.
+     */
+    public boolean isError()
+    {
+        return this.m_error != null ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/CursorListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,20 @@
+/*
+ * $Id: CursorListener.java,v 1.2 2003/03/13 18:26:50 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.EventListener ;
+
+
+public interface CursorListener
+    extends EventListener
+{
+	void cursorAdvanced(CursorEvent an_event) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EmptyCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EmptyCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,49 @@
+/*
+ * $Id: EmptyCursor.java,v 1.2 2003/03/13 18:26:51 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.NoSuchElementException ;
+
+
+/**
+ * An empty cursor that is closed on creation! Used as annon inner class in so
+ * many places I had to create it.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class EmptyCursor
+    extends Cursor
+{
+    /**
+     * Closes on creation.
+     */
+    public EmptyCursor()
+    {
+        try { close() ; } catch(Exception e) {} ;
+    }
+
+    /**
+     * Throws NoSuchElementException all the time.
+     */
+    public Object advance() { throw new NoSuchElementException() ; }
+
+    /**
+     * Always returns false.
+     */
+    public boolean canAdvance() { return false ; }
+
+    /**
+     * Does nothing.
+     */
+    public void freeResources() { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EnumerationCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/EnumerationCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,61 @@
+/*
+ * $Id: EnumerationCursor.java,v 1.2 2003/03/13 18:26:52 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Enumeration ;
+
+
+/**
+ * A cursor using an underlying Enumeration.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class EnumerationCursor
+    extends Cursor
+{
+    private final Enumeration m_enumeration ;
+
+    /**
+     * Creates a cursor over an Enumeration.
+     * 
+     * @param a_enumeration the underlying Enumeration this cursor uses.
+     */
+    public EnumerationCursor(Enumeration a_enumeration)
+    {
+        m_enumeration = a_enumeration ;
+    }
+
+
+    /**
+     * Returns enumeration.nextElement()
+     * @return enumeration.nextElement()
+     */
+    public Object advance()
+    {
+        return m_enumeration.nextElement() ;
+    }
+
+
+    /**
+     * Returns enumeration.hasMoreElements()
+     * @return Returns enumeration.hasMoreElements()
+     */
+    public boolean canAdvance()
+    {
+        return m_enumeration.hasMoreElements() ;
+    }
+
+
+    /** Does nothing */
+    public void freeResources() { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/IteratorCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/IteratorCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,55 @@
+/*
+ * $Id: IteratorCursor.java,v 1.2 2003/03/13 18:26:54 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Iterator ;
+
+
+/**
+ * A cursor using an underlying Iterator.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class IteratorCursor
+    extends Cursor
+{
+    private final Iterator m_iterator ;
+
+    /**
+     * Creates a cursor over an Iterator.
+     * 
+     * @param a_iterator the underlying iterator this cursor uses.
+     */
+    public IteratorCursor(Iterator a_iterator)
+    {
+        m_iterator = a_iterator ;
+    }
+
+
+    /** Returns iterator.next() */
+    public Object advance()
+    {
+        return m_iterator.next() ;
+    }
+
+
+    /** Returns iterator.hasNext() */
+    public boolean canAdvance()
+    {
+        return m_iterator.hasNext() ;
+    }
+
+
+    /** Does nothing */
+    public void freeResources() { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/LdapEntry.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/LdapEntry.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,297 @@
+/*
+ * $Id: LdapEntry.java,v 1.8 2003/03/13 18:26:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+import java.math.BigInteger ;
+import java.io.Serializable ;
+
+import java.util.Date ;
+import java.util.Collection ;
+
+import javax.naming.Name ;
+import javax.naming.directory.SchemaViolationException ;
+import javax.naming.directory.AttributeModificationException ;
+import javax.naming.directory.InvalidAttributeValueException ;
+import javax.naming.directory.InvalidAttributeIdentifierException ;
+import javax.naming.directory.AttributeInUseException ;
+import java.util.Iterator;
+import org.apache.eve.schema.Schema;
+import javax.naming.NamingException;
+
+
+/**
+ * Internal server side representation of an LDAP entry.  All backend entry
+ * implementations are expected to implement this interface.  The interface
+ * defines standard house keeping attributes used by this LDAP v3
+ * implementation.
+ *
+ * @task We need to explicitly outline some semantics for the various house
+ * keeping constants - like the parent id of the suffix entry should always be
+ * itself etc.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.8 $
+ * @see Backend
+ */
+public interface LdapEntry
+    extends Serializable
+{
+    /**
+     * The identifier of the Distinguished name attribute for this entry.  The
+     * value of this attribute is NOT a normalized DN it is the user provide 
+     * DN.
+     *
+     * @see getEntryDN
+     */
+    String DN_ATTR = Schema.DN_ATTR ;
+    /**
+     * The identifier of the normalized Distinguished name attribute for this
+     * Entry's parent.
+     * 
+     * @see getParentDN
+     */
+    String PARENTDN_ATTR = "parentdn" ;
+    /**
+     * The identifier of the normalized Distinguished name attribute for this
+     * Entry's subschema subentry.
+     * 
+     * @see getSubschemaSubentry
+     */
+    String SUBSCHEMASUBENTRY_ATTR = "subschemasubentry" ;
+    /**
+     * The identifier of the normalized Distinguished name attribute for this
+     * Entry's creator.
+     * 
+     * @see getCreatorsName
+     */
+    String CREATORSNAME_ATTR = "creatorsname" ;
+    /**
+     * The identifier of the normalized Distinguished name attribute for this
+     * Entry's last modifier.
+     * 
+     * @see getModifiersName
+     */
+    String MODIFIERSNAME_ATTR = "modifiersname" ;
+    /** Unique entry identifier attribute's name */
+    String ID_ATTR = "entryid" ;
+    /** Entry's parent id attribute's identifier */
+    String PARENTID_ATTR = Schema.HIERARCHY_ATTR ;
+    /** Number of subordinates attribute's identifier */
+    String NUMSUBORDINATES_ATTR = "numsubordinates" ;
+    /** Create timestamp attribute's identifier */
+    String CREATETIMESTAMP_ATTR = "createtimestamp" ;
+    /** Modifier's timestamp attribute's identifier */
+    String MODIFYTIMESTAMP_ATTR = "modifytimestamp" ;
+
+    Collection attributes() ;
+
+    boolean hasAttribute(String an_attributeName) ;
+
+    /**
+     * Checks whether or not this Entry is a valid entry residing within a
+     * backend.  Entries are validated on successful create() calls.  When
+     * Entry instances are initialized in the java sense via the newEntry()
+     * call on backends, they are in the invalid state.
+     *
+     * @return true if this entry has been persisted to a backend,
+     * false otherwise.
+     */
+    boolean isValid() ;
+
+    /**
+     * Gets this entry's creation timestamp as a Date.
+     *
+     * @return Date representing the creation timestamp of this entry.
+     */
+    Date getCreateTimestamp() ;
+
+    /**
+     * Gets this entry's modification timestamp as a Date.
+     *
+     * @return Date representing the timestamp this entry was last modified.
+     */
+    Date getModifyTimestamp() ;
+
+    /**
+     * Gets the unique distinguished name associated with this entry as it was
+     * supplied during creation without whitespace trimming or character case
+     * conversions.  This version of the DN is kept within the body of this
+     * Entry as an operational attribute so that it could be returned as it was
+     * given to the server w/o normalization effects: case and whitespace will
+     * be entact.
+     *
+     * @return the distinguished name of this entry as a String.
+     */
+    String getEntryDN() ;
+
+    /**
+     * Gets the normalized unique distinguished name associated with this 
+     * entry. This DN unlike the user specified DN accessed via getDN() is not
+     * an operational attribute composing the body of this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this entry as a String.
+     */
+    Name getNormalizedDN()
+        throws NamingException ;
+
+    Name getUnNormalizedDN()
+        throws NamingException ;
+
+    /**
+     * Gets the normalized unique distinguished name of this Entry's parent.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this Entry's parent.
+     */
+    String getParentDN() ;
+
+    /**
+     * Gets the distinguished name of the creator of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the distinguished name of the creator.
+     */
+    String getCreatorsName() ;
+
+    /**
+     * Gets the distinguished name of the last modifier of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the DN of the user to modify this entry last.
+     */
+    String getModifiersName() ;
+
+    Schema getSchema() ;
+
+    /**
+     * Gets the distinguished name of the subschema subentry for this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return String of the subschema subentry distinguished name.
+     */
+    String getSubschemaSubentryDN() ;
+
+    /**
+     * Gets a single valued attribute by name or returns the first value of a
+     * multivalued attribute.
+     *
+     * @param a_attribName the name of the attribute to lookup.
+     * @return an Object value which is either a String or byte [] or null if
+     * the attribute does not exist.
+     */
+    Object getSingleValue(String an_attribName) ;
+
+    /**
+     * Gets a multivalued attribute by name.
+     *
+     * @param a_attribName the name of the attribute to lookup.
+     * @return a Collection or null if no attribute value exists.
+     */
+    Collection getMultiValue(String an_attribName) ;
+
+    /**
+     * Adds a value to this Entry potentially resulting in more than one value
+     * for the attribute/key.
+     * 
+     * @param an_attribName attribute name/key
+     * @param a_value the value to add
+     * @throws InvalidAttributeIdentifierException when an attempt is made to
+     * add to or create an attribute with an invalid attribute identifier.
+     * @throws InvalidAttributeValueException when an attempt is made to add to
+     * an attribute a value that conflicts with the attribute's schema
+     * definition. This could happen, for example, if attempting to add an
+     * attribute with no value when the attribute is required to have at least
+     * one value, or if attempting to add more than one value to a single
+     * valued-attribute, or if attempting to add a value that conflicts with 
+     * the syntax of the attribute.
+     */
+    void addValue(String an_attribName, Object a_value)
+        throws
+        AttributeInUseException,
+        InvalidAttributeValueException,
+        InvalidAttributeIdentifierException ;
+
+    /**
+     * Removes the attribute/value pair in this Entry only without affecting
+     * other values that the attribute may have.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_value the value to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    void removeValue(String an_attribName, Object a_value)
+        throws InvalidAttributeIdentifierException ;
+
+    /**
+     * Removes the specified set of attribute/value pairs in this Entry.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_valueArray the set of values to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    void removeValues(String an_attribName, Object [] a_valueArray)
+        throws InvalidAttributeIdentifierException ;
+
+    /**
+     * Removes all the attribute/value pairs in this Entry associated with the
+     * attribute.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_value the value to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    void removeValues(String an_attribName)
+        throws InvalidAttributeIdentifierException ;
+
+    /**
+     * Checks to see if this LdapEntry is equal to an entry with a Dn.
+     *
+     * @param a_dn the dn to test for equality.
+     * @return true if this entry has a Dn equal to a_dn, false otherwise.
+     */
+    boolean equals(String a_dn)
+        throws NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/NexusModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/NexusModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,730 @@
+/*
+ * $Id: NexusModule.java,v 1.26 2003/08/22 21:15:54 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import org.apache.eve.AbstractModule ;
+
+import java.util.Map ;
+import java.util.Date ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+
+import javax.naming.Name ;
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+import javax.naming.InvalidNameException ;
+import javax.naming.NameNotFoundException ;
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.ldap.common.filter.ExprNode ;
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.client.ClientManager ;
+import org.apache.eve.schema.SchemaManager ;
+import org.apache.eve.client.ClientSession ;
+import org.apache.eve.client.ClientManagerSlave ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+
+/**
+ * Default backend nexus or unified backend implementation for the server.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.backend.UnifiedBackend"
+ * @phoenix:mx-topic name="backend-nexus"
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.26 $
+ */
+public class NexusModule
+    extends AbstractModule
+    implements UnifiedBackend, ClientManagerSlave
+{
+    /** Config tag for RootDSE definition */
+    public static final String ROOTDSE_TAG = "RootDSE" ;
+    /** Config tag for RootDSE attributes */
+	public static final String ATTRIBUTE_TAG = "attribute" ;
+
+    ClientManager m_clientMan = null ;
+    SchemaManager m_schemaMan = null ;
+    Schema m_schema = null ;
+    RootDSE m_rootDSE = null ;
+
+    /** Map of backend normalized suffix strings to backends */
+    Map m_backends = new HashMap() ;
+    Map m_repListeners = new HashMap() ;
+    Map m_adminUsers = new HashMap() ;
+
+
+    // -------------------------------------------------------
+    // Operational Attribute Management Methods
+    // -------------------------------------------------------
+
+
+    /**
+     * Sets an entries operational attributes based on client session parameters
+     * and whether or not the operation is a create or an update.
+     *
+     * @param an_entry the entry to add or alter the operational attributes of.
+     * @param isCreate true if op attrs are added for create or false for update
+     */
+    private void setOperationalAttributes( LdapEntry an_entry,
+        boolean isCreate ) throws BackendException, NamingException
+    {
+        String l_now = new Date().toGMTString() ;
+        String l_userDn = null ;
+        ClientSession l_session = m_clientMan.getClientSession() ;
+
+        if( null == l_session )
+        {
+            throw new BackendException(
+                "Cannot obtain client session object!" ) ;
+        }
+
+        // Get authenticated principal's Dn
+        l_userDn = l_session.getPrincipal().getDn().toString() ;
+
+        if( isCreate )
+        {
+            if( an_entry.hasAttribute( LdapEntry.CREATETIMESTAMP_ATTR ) )
+            {
+                an_entry.removeValues( LdapEntry.CREATETIMESTAMP_ATTR ) ;
+            }
+
+            if( an_entry.hasAttribute( LdapEntry.CREATORSNAME_ATTR ) )
+            {
+                an_entry.removeValues( LdapEntry.CREATORSNAME_ATTR ) ;
+            }
+
+            an_entry.addValue( LdapEntry.CREATETIMESTAMP_ATTR, l_now ) ;
+            an_entry.addValue( LdapEntry.CREATORSNAME_ATTR, l_userDn ) ;
+        }
+
+        if( an_entry.hasAttribute( LdapEntry.MODIFYTIMESTAMP_ATTR ) )
+        {
+            an_entry.removeValues( LdapEntry.MODIFYTIMESTAMP_ATTR ) ;
+        }
+
+        if( an_entry.hasAttribute( LdapEntry.MODIFIERSNAME_ATTR ) )
+        {
+            an_entry.removeValues( LdapEntry.MODIFIERSNAME_ATTR ) ;
+        }
+
+        an_entry.addValue( LdapEntry.MODIFYTIMESTAMP_ATTR, l_now ) ;
+        an_entry.addValue( LdapEntry.MODIFIERSNAME_ATTR, l_userDn ) ;
+    }
+
+
+    // -------------------------------------------------------
+    // CRUD Method Implementations
+    // -------------------------------------------------------
+
+
+    public void create( LdapEntry an_entry )
+        throws BackendException, NamingException
+    {
+        setOperationalAttributes ( an_entry, true ) ;
+        getBackend( an_entry.getNormalizedDN() ).create( an_entry ) ;
+    }
+
+
+    public LdapEntry newEntry( String a_dn )
+        throws BackendException, NamingException
+    {
+        return getBackend( getNormalizedName( a_dn ) ).newEntry( a_dn ) ;
+    }
+
+
+    public LdapEntry read( Name a_dn )
+        throws BackendException, NamingException
+    {
+        return getBackend(
+            getNormalizedName( a_dn.toString() ) ).read( a_dn ) ;
+    }
+
+
+    public void update(LdapEntry an_entry)
+        throws BackendException, NamingException
+    {
+        setOperationalAttributes (an_entry, false) ;
+        getBackend( an_entry.getNormalizedDN() ).update(an_entry) ;
+    }
+
+
+    public void delete( LdapEntry an_entry )
+        throws BackendException, NamingException
+    {
+        getBackend( an_entry.getNormalizedDN() ).delete( an_entry ) ;
+    }
+
+
+    public LdapEntry getParent(Name a_childDn)
+        throws BackendException, NamingException
+    {
+        return getBackend(a_childDn).getParent(a_childDn) ;
+    }
+
+
+    public boolean hasEntry(Name a_dn)
+        throws BackendException, NamingException
+    {
+        return getBackend(a_dn).hasEntry(a_dn) ;
+    }
+
+
+    public boolean isSuffix(LdapEntry an_entry)
+    {
+        try {
+        	return getBackend(an_entry.getNormalizedDN()).isSuffix(an_entry) ;
+        } catch(NamingException e) {
+            // Should never really be thrown.
+            return false ;
+        }
+    }
+
+
+    public Name getNormalizedName(String a_name)
+        throws NamingException
+    {
+        return m_schema.getNormalizingParser().parse(a_name) ;
+    }
+
+
+    public Name getName(String a_name)
+        throws NamingException
+    {
+        return m_schema.getNameParser().parse(a_name) ;
+    }
+
+
+    /**
+     * V E R Y   I N E F F I C I E N T
+     * 
+     * This could be made much more efficient by hashing all the normalized
+     * admin user names against their backends in a hashmap and doing the
+     * lookup after converting the a_userDn arguement into its canonical form.
+     */
+    public boolean isAdminUser(Name a_userDn)
+        throws NamingException
+    {
+        if(m_adminUsers.containsKey(a_userDn.toString())) {
+            return true ;
+        }
+
+        return false ;
+    }
+
+
+    public RootDSE getRootDSE()
+    {
+        return m_rootDSE ;
+    }
+
+
+    public Cursor listChildren(Name a_parentDn)
+        throws BackendException, NamingException
+    {
+        return getBackend(a_parentDn).listChildren(a_parentDn) ;
+    }
+
+
+    public Cursor search(ExprNode a_searchFilter, Name a_baseDn,
+		  int a_scope)
+        throws BackendException, NamingException
+    {
+        // Base search without a namespace returns the RootDSE within a
+        // SingletonCursor that returns only one entry: the RootDSE.
+        if(a_baseDn.toString().trim().equals("") && a_scope == BASE_SCOPE) {
+            return new SingletonCursor(m_rootDSE) ;
+        }
+
+        return getBackend(a_baseDn).search(a_searchFilter,
+            a_baseDn, a_scope) ;
+    }
+
+
+    /**
+     * Modifies the relative distinguished name (RDN) of an entry without 
+     * changing any parent child relationships.  This call has the side effect 
+     * of altering the distinguished name of descendent entries if they exist.
+     * The boolean argument will optionally remove the existing RDN attribute 
+     * value pair replacing it with the new RDN attribute value pair.  If other
+	 * RDN attribute value pairs exist besides the current RDN they will be 
+     * spared.
+     * 
+     * If the new Rdn and the old Rdn are equal this method does nothing.
+     *
+     * @param an_entry the entry whose RDN is to be modified.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void modifyRdn( LdapEntry an_entry, Name a_newRdn,
+        boolean a_deleteOldRdn ) 
+	    throws BackendException, NamingException
+    {
+        AtomicBackend l_be = getBackend( an_entry.getNormalizedDN() ) ;
+        Name l_dn = new LdapName( an_entry.getEntryDN() ) ;
+        String l_oldRdnStr = l_dn.get( l_dn.size() - 1 ) ;
+        String l_newRdnStr = a_newRdn.get( a_newRdn.size() - 1 ) ;
+        
+        // Set common operational attributes on the entry first
+        setOperationalAttributes( an_entry, false ) ;
+        
+        // Only perform modifyRdn operation if newRdn is not the same as old
+        if ( ! l_oldRdnStr.equals( l_newRdnStr ) ) 
+        {
+            l_be.modifyRdn( an_entry, a_newRdn, a_deleteOldRdn ) ;
+        }
+
+        getBackend(an_entry.getNormalizedDN()).
+            modifyRdn(an_entry, a_newRdn, a_deleteOldRdn) ;
+    }
+
+
+    /**
+     * This overload combines the first two method operations into one.
+     * It changes the Rdn and the parent prefix at the same time while
+	 * recursing name changes to all descendants of the child entry. It
+	 * is obviously more complex than the other two operations alone and
+	 * involves changes to both parent child indices and DN indices.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move( LdapEntry a_parentEntry, LdapEntry a_childEntry,
+	    Name a_newRdn, boolean a_deleteOldRdn )
+	    throws BackendException, NamingException
+    {
+        AtomicBackend l_be = getBackend( a_parentEntry.getNormalizedDN() ) ;
+        Name l_childDn = new LdapName( a_childEntry.getEntryDN() ) ;
+        String l_oldRdnStr = l_childDn.get( l_childDn.size() - 1 ) ;
+        String l_newRdnStr = a_newRdn.get( a_newRdn.size() - 1 ) ;
+        
+        Name l_normalizedChildDn = a_childEntry.getNormalizedDN() ;
+        Name l_normalizedOldParentDn = 
+            l_normalizedChildDn.getPrefix( l_normalizedChildDn.size() - 1 ) ;
+
+        // Set common operational attributes on the entry first
+        setOperationalAttributes( a_childEntry, false ) ;
+
+
+        if ( l_normalizedOldParentDn.equals( a_parentEntry.getNormalizedDN() ) ) 
+        {
+            if ( l_oldRdnStr.equals( l_newRdnStr ) )
+            {
+                /*
+                 * The new and old rdn are the same and the new and old parents
+                 * are the same as well so we do nothing.  Both rdn renames and
+                 * move operations are pointless so we return.
+                 */
+                return ;
+            }
+            
+            /*
+             * The move operation is unnecessary but the rdn change is valid
+             * so we transduce this call to a modifyRdn call on the backend
+             */
+            l_be.modifyRdn( a_childEntry, a_newRdn, a_deleteOldRdn ) ;
+        }
+        else 
+        {
+            if ( l_oldRdnStr.equals( l_newRdnStr ) ) 
+            {
+                /*
+                 * The new and old rdn are the same so we convert this to a 
+                 * simple move operation.
+                 */
+                l_be.move( a_parentEntry, a_childEntry ) ;
+            } 
+            else 
+            {
+                // Both the move and the rdn change are necessary here!
+                l_be.move( a_parentEntry, a_childEntry, a_newRdn, 
+                    a_deleteOldRdn ) ;
+            }
+        }
+    }
+
+
+    /**
+     * Moves a child entry without changing the RDN under a new parent entry.  
+     * This effects the parent child relationship between the parent entry and 
+     * the child entry.  The index for the child mapping it to the current 
+     * parent is destroyed and a new index mapping it to the new parent is 
+     * created.  As a side effect the name of the child entry and all its 
+     * descendants will reflect the move within the DIT to a new parent.  The 
+     * old parent prefix to the distinguished names of the child and its 
+     * descendents will be replaced by the new parent DN prefix.
+     * 
+     * If the new parent is the same as the old parent this call does nothing
+     * since the operation is pointless.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move( LdapEntry a_parentEntry, LdapEntry a_childEntry )
+	    throws BackendException, NamingException
+    {
+        AtomicBackend l_be = getBackend( a_parentEntry.getNormalizedDN() ) ;
+        Name l_dn = a_childEntry.getNormalizedDN() ;
+        Name l_oldParentDn = l_dn.getPrefix( l_dn.size() - 1 ) ;
+        
+        // Fires ModifyProtocolEvent
+        setOperationalAttributes( a_childEntry, false ) ;
+        
+        // Only perform operation if new parent dn is different from the old 
+        if ( ! a_parentEntry.getNormalizedDN().equals( l_oldParentDn ) )
+        {
+            l_be.move( a_parentEntry, a_childEntry ) ;
+        }
+    }
+
+
+    //////////////////////////////////////////////
+    // UnifiedBackend Interface Implementations //
+    //////////////////////////////////////////////
+
+
+    /**
+     * Gets the suffix of the backend responsible for an entry using the entry's
+     * distinguished name.
+     *
+     * @phoenix:mx-operation
+     * @phoenix:mx-description Gets the suffix of the backend storing an entry
+     * by its DN.
+     */
+    public String getBackendSuffixForEntry(String a_dn)
+        throws InvalidNameException, NameNotFoundException
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+
+        l_buf.append("Repsonsible backend module suffix for entry ") ;
+        l_buf.append(a_dn).append(':').append("\n") ;
+	    l_buf.append("=================================") ;
+	    l_buf.append("=================================\n") ;
+	    l_buf.append("\n\n") ;
+
+        try {
+            Name l_dn = getNormalizedName (a_dn) ;
+            BackendModule l_be = (BackendModule) getBackend(l_dn) ;
+            l_buf.append(l_be.getImplementationName()).append("\n") ;
+            l_buf.append(l_be.getSuffix()).append("\n") ;
+        } catch(Throwable t) {
+            l_buf.append(ExceptionUtil.printStackTrace(t)) ;
+        }
+
+        return l_buf.toString() ;
+    }
+
+
+    /**
+     * Gets the most significant Dn that exists within the server and hence can
+     * be matched to an actual entry.
+     *
+     * @param a_dn to use for the matching test.
+     * @return the matching portion of a_dn, or the valid empty string dn if no
+     * match was found.
+     */
+    public Name getMatchedDn( Name a_dn )
+        throws NamingException, BackendException
+    {
+		LdapName l_suffix ;
+
+        // Don't try to match for the empty dn which matches by default if we
+        // try to match it in hasEntry then we will get a failure to find an
+        // atomic backend for it.
+        if( a_dn.size() == 0 )
+        {
+            return a_dn ;
+        }
+        // Return if a_dn itself is matched/exists.
+        else if( hasEntry( a_dn ) )
+        {
+            return a_dn ;
+        }
+
+        // Otherwise we start removing most significant components from the head
+        // of it looking for a suffix dn that matches until the "" dn results
+        l_suffix = ( LdapName ) a_dn.clone() ;
+		while( l_suffix.size() > 0 )
+        {
+			l_suffix.remove( l_suffix.size() - 1 ) ;
+
+            // Short loop on a match
+            if( hasEntry( l_suffix ) )
+            {
+                return l_suffix ;
+            }
+		}
+
+        // Should be the empty string distinguished name
+        return l_suffix ;
+    }
+
+
+    /**
+     * Gets the backend associated with a distinguished name if the name
+     * resolves to a suffix.
+     *
+     * @param a_dn the distinguished name to resolve to a backend
+     */
+    public AtomicBackend getBackend( Name a_dn )
+        throws NamingException
+    {
+        Name l_suffix = null ;
+        Iterator l_list = null ;
+        AtomicBackend l_backend = null ;
+
+        if( ! hasStarted() )
+        {
+            throw new IllegalStateException( "Module has not started!" ) ;
+        }
+
+        if( getLogger().isDebugEnabled() )
+        {
+            getLogger().debug("" //ProtocolModule.getMessageKey()
+                + " - NexusModule.getBackend(): Request for DN " + a_dn) ;
+        }
+
+		// First lets just see if l_dn is a suffix to begin with using a cheap
+        // lookup in the normalized suffix String to backend Hash map.
+	    if( m_backends.containsKey( a_dn.toString() ) )
+        {
+            BackendModule l_be =
+                ( BackendModule ) m_backends.get( a_dn.toString() ) ;
+
+            if( getLogger().isDebugEnabled() )
+            {
+                getLogger().debug("" //ProtocolModule.getMessageKey()
+                    + " - NexusModule.getBackend(): Request for DN " + a_dn
+                    + " returning " + l_be.getImplementationName()
+                    + " with suffix " + l_be.getSuffix() ) ;
+            }
+
+            return l_be ;
+        }
+
+        // So l_dn
+		l_list = listBackends() ;
+        while( l_list.hasNext() )
+        {
+	        l_backend = ( AtomicBackend ) l_list.next() ;
+            l_suffix = l_backend.getSuffix() ;
+            if( a_dn.startsWith( l_suffix ) )
+            {
+                if( getLogger().isDebugEnabled() )
+                {
+                    getLogger().debug( "" //ProtocolModule.getMessageKey()
+                        + " - NexusModule.getBackend(): returning backend "
+                        + l_suffix ) ;
+                }
+                return l_backend ;
+            }
+        }
+
+        // After this point we are screwed!
+        if( getLogger().isDebugEnabled() )
+        {
+            getLogger().debug( "Valid name " + a_dn + " not found under nexus "
+                + "backends.  Throwing IllegalArgumentException!" ) ;
+        }
+
+        throw new IllegalArgumentException( a_dn + " not a valid namespace - "
+            + "could not find matching backend!" ) ;
+    }
+
+
+    public NameParser getNameParser()
+    {
+        return m_schema.getNameParser() ;
+    }
+
+
+    public NameParser getNormalizingParser()
+    {
+        return m_schema.getNormalizingParser() ;
+    }
+
+
+    public NameParser getNormalizingParser(Name a_name)
+        throws NamingException
+    {
+        Schema l_schema = this.getSchema(a_name) ;
+        if(l_schema != null) {
+            return l_schema.getNormalizingParser() ;
+        }
+
+        return null ;
+    }
+
+
+    /**
+     * JMX intended operation to list registered running backends this nexus
+     * currently has attacked to it.
+     * 
+     * @phoenix:mx-operation
+     * @phoenix:mx-description Lists all atomic backends registered with the
+     * nexus (or system unified backend).
+     */
+    public String getRegisteredBackends()
+    {
+		StringBuffer l_buf = new StringBuffer() ;
+
+		l_buf.append("Nexus attached backend modules:").append("\n") ;
+		l_buf.append("=================================") ;
+		l_buf.append("=================================\n") ;
+		l_buf.append("\n\n") ;
+
+		Iterator l_list = listBackends() ;
+       	while(l_list.hasNext()) {
+        	BackendModule l_backend = (BackendModule) l_list.next() ;
+
+            l_buf.append("Implementation Name:\t") ;
+            l_buf.append(l_backend.getImplementationName()).append("\n") ;
+
+            l_buf.append("Implementation Class Name:\t") ;
+            l_buf.append(l_backend.getImplementationClassName()).append("\n") ;
+
+            l_buf.append("Suffix Serviced:\t") ;
+            l_buf.append(l_backend.getSuffix()).append("\n\n\n") ;
+       }
+
+       return l_buf.toString() ;
+    }
+
+
+    public Iterator listBackends()
+    {
+        return m_backends.values().iterator() ;
+    }
+
+
+    public Iterator listSuffixes()
+    {
+        return m_backends.keySet().iterator() ;
+    }
+
+
+    public void register( AtomicBackend a_backend )
+    {
+        // Dynamically register client manager with backends added on fly.
+        a_backend.registerClientManager( m_clientMan ) ;
+        m_backends.put( a_backend.getSuffix().toString(), a_backend ) ;
+        m_adminUsers.put( a_backend.getAdminUserDN().toString(), a_backend ) ;
+    }
+
+
+    public void unregister(AtomicBackend a_backend)
+    {
+        m_backends.remove(a_backend.getSuffix().toString()) ;
+        m_adminUsers.remove(a_backend.getAdminUserDN().toString()) ;
+    }
+
+
+    ///////////////////////////////////////
+    // Life-cycle Method Implementations //
+    ///////////////////////////////////////
+
+
+    /**
+     * We use this to get a handle on the schema manager.
+     * 
+     * @phoenix:dependency name="org.apache.eve.schema.SchemaManager"
+     * @param a_manager the service manager that we get a BackendManager from
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        m_schemaMan =
+            (SchemaManager) a_manager.lookup(SchemaManager.ROLE) ;
+        m_schema = m_schemaMan.getCompleteSchema() ;
+    }
+
+
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+        m_rootDSE = new RootDSE(m_schema) ;
+
+        try {
+			Configuration l_dseConfig = a_config.getChild(ROOTDSE_TAG, false) ;
+			if(l_dseConfig == null) {
+				String l_errmsg = "The " + ROOTDSE_TAG + " does not exist in "
+					+ "the configuration section for the NexusModule. Cannot "
+					+ "continue configuration without it!" ;
+				throw new ConfigurationException(l_errmsg) ;
+			}
+	
+			Configuration [] l_attributes = l_dseConfig.getChildren(ATTRIBUTE_TAG) ;
+			for(int ii = 0 ; ii < l_attributes.length ; ii++ ) {
+				String l_name = l_attributes[ii].getAttribute("name", null) ;
+				String l_value = l_attributes[ii].getAttribute("value", null) ;
+				m_rootDSE.addValue(l_name, l_value) ;
+			}
+        } catch(Throwable e) {
+            String l_errmsg = "Encountered error while trying to construct the"
+                + " RootDSE during the NexusModule's configuration stage." ;
+            throw new ConfigurationException(l_errmsg, e) ;
+        }
+    }
+
+
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    public String getImplementationName()
+    {
+        return "Unified Backend Nexus" ;
+    }
+
+
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    public void registerClientManager(ClientManager a_manager)
+    {
+        m_clientMan = a_manager ;
+    }
+
+
+    public Schema getSchema(Name a_dn)
+        throws NamingException
+    {
+        BackendModule l_be = (BackendModule) getBackend(a_dn) ;
+		return l_be.getSchema() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/NormalizerComponent.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/ReadOnlyException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/ReadOnlyException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,35 @@
+/*
+ * $Id: ReadOnlyException.java,v 1.4 2003/07/29 22:08:02 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import javax.naming.OperationNotSupportedException ;
+
+
+/**
+ * This exception is thrown when write operations are attempted against a
+ * Backend configured to be read-only.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public class ReadOnlyException
+    extends OperationNotSupportedException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param a_message The message associated with the exception.
+     */
+    public ReadOnlyException(String a_message)
+    {
+        super(a_message) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/RootDSE.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/RootDSE.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,414 @@
+/*
+ * $Id: RootDSE.java,v 1.3 2003/03/13 18:27:00 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Date ;
+import java.util.Collection ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.directory.AttributeInUseException ;
+import javax.naming.directory.InvalidAttributeValueException ;
+import javax.naming.directory.InvalidAttributeIdentifierException ;
+
+import org.apache.commons.collections.MultiHashMap ;
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.eve.schema.Schema ;
+
+
+/**
+ * An entry implementation for the Berkeley backend.
+ * 
+ * @task No schema checking going on right now - but this needs to change!
+ * @task Also we need to make sure that we are storing dates in the apropriate
+ * fashion
+ */
+public class RootDSE
+    extends MultiHashMap
+	implements LdapEntry
+{
+    private final Schema m_schema ;
+    private final Name m_dn = new LdapName() ;
+    private boolean m_isValid = false ;
+
+
+    RootDSE(Schema a_schema)
+    {
+        m_schema = a_schema ;
+    }
+
+
+    public Collection attributes()
+    {
+        return this.keySet() ;
+    }
+
+
+    public Schema getSchema()
+    {
+        return m_schema ;
+    }
+
+
+	public boolean equals(String a_dn)
+        throws NamingException
+    {
+        if(a_dn == null) {
+            return false ;
+        }
+
+        return a_dn.trim().equals("") ;
+    }
+
+
+    public boolean hasAttribute(String an_attributeName)
+    {
+        return containsKey(an_attributeName) ;
+    }
+
+
+    public boolean hasAttributeValuePair(String an_attribute, Object a_value)
+    {
+        if(containsKey(an_attribute)) {
+            Collection l_collection = getMultiValue(an_attribute) ;
+
+            if(null == l_collection && null == a_value) {
+                return true ;
+            } else if(null == l_collection || null == a_value) {
+                return false ;
+            } else if(l_collection.contains(a_value)) {
+                return true ;
+            } else {
+                return false ;
+            }
+        } else {
+	    return false ;
+        }
+    }
+
+
+    /**
+     * Gets this entry's creation timestamp as a Date.
+     *
+     * @return Date representing the creation timestamp of this entry.
+     */
+    public Date getCreateTimestamp()
+    {
+	return new Date((String) getSingleValue(CREATETIMESTAMP_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the creator of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the distinguished name of the creator.
+     */
+    public String getCreatorsName()
+    {
+        return (String) getSingleValue(CREATORSNAME_ATTR) ;
+    }
+
+
+    /**
+     * Gets the unique distinguished name associated with this entry as it was
+     * supplied during creation without whitespace trimming or character case
+     * conversions.  This version of the DN is kept within the body of this
+     * Entry as an operational attribute so that it could be returned as it was
+     * given to the server w/o normalization effects: case and whitespace will
+     * be entact.
+     *
+     * @return the distinguished name of this entry as a String.
+     */
+    public String getEntryDN()
+    {
+        return (String) getSingleValue(DN_ATTR) ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the last modifier of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the DN of the user to modify this entry last.
+     */
+    public String getModifiersName()
+    {
+        return (String) getSingleValue(MODIFIERSNAME_ATTR) ;
+    }
+
+
+    /**
+     * Gets this entry's modification timestamp as a Date.
+     *
+     * @return Date representing the timestamp this entry was last modified.
+     */
+    public Date getModifyTimestamp()
+    {
+        return new Date((String)
+            getSingleValue(MODIFYTIMESTAMP_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the normalized unique distinguished name associated with this 
+     * entry. This DN unlike the user specified DN accessed via getDN() is not
+     * an operational attribute composing the body of this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this entry as a String.
+     */
+    public Name getNormalizedDN()
+        throws NamingException
+    {
+        return m_dn ;
+    }
+
+
+    public Name getUnNormalizedDN()
+        throws NamingException
+    {
+        return m_dn ;
+    }
+
+
+    /**
+     * Gets the normalized unique distinguished name of this Entry's parent.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this Entry's parent.
+     */
+    public String getParentDN()
+    {
+        return (String) getSingleValue(PARENTDN_ATTR) ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the subschema subentry for this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return String of the subschema subentry distinguished name.
+     */
+    public String getSubschemaSubentryDN()
+    {
+        return (String) getSingleValue(SUBSCHEMASUBENTRY_ATTR) ;
+    }
+
+
+    /**
+     * Checks whether or not this Entry is a valid entry residing within a
+     * backend.  Entries are validated on successful create() calls.  When
+     * Entry instances are initialized in the java sense via the newEntry()
+     * call on backends, they are in the invalid state.
+     *
+     * @return true if this entry has been persisted to a backend,
+     * false otherwise.
+     */
+    public boolean isValid()
+    {
+        return m_isValid ;
+    }
+
+
+    /**
+     * Gets a multivalued attribute by name.
+     *
+     * @param an_attribName the name of the attribute to lookup.
+     * @return a Collection or null if no attribute value exists.
+     */
+    public Collection getMultiValue(String an_attribName)
+    {
+        return (Collection) get(an_attribName) ;
+    }
+
+
+    /**
+     * Gets a single valued attribute by name or returns the first value of a
+     * multivalued attribute.
+     *
+     * @param an_attribName the name of the attribute to lookup.
+     * @return an Object value which is either a String or byte [] or null if
+     * the attribute does not exist.
+     */
+    public Object getSingleValue(String an_attribName)
+    {
+        Collection l_col = (Collection) get(an_attribName) ;
+
+		if(null == l_col || l_col.isEmpty()) {
+            return null ;
+        }
+
+        return l_col.iterator().next() ;
+    }
+
+
+    /**
+     * Adds a value to this Entry potentially resulting in more than one value
+     * for the attribute/key.
+     * 
+     * @param an_attribName attribute name/key
+     * @param a_value the value to add
+     * @throws InvalidAttributeIdentifierException when an attempt is made to
+     * add to or create an attribute with an invalid attribute identifier.
+     * @throws InvalidAttributeValueException when an attempt is made to add to
+     * an attribute a value that conflicts with the attribute's schema
+     * definition. This could happen, for example, if attempting to add an
+     * attribute with no value when the attribute is required to have at least
+     * one value, or if attempting to add more than one value to a single
+     * valued-attribute, or if attempting to add a value that conflicts with 
+     * the syntax of the attribute.
+     */
+    public void addValue(String an_attribName, Object a_value)
+        throws
+        AttributeInUseException,
+        InvalidAttributeValueException,
+        InvalidAttributeIdentifierException
+    {
+	    if(null == a_value || null == an_attribName) {
+            return ;
+        }
+
+        if(!m_schema.hasAttribute(an_attribName)) {
+            throw new InvalidAttributeIdentifierException(an_attribName +
+                " is not a valid schema recognized attribute name.") ;
+        }
+
+		if(containsKey(an_attribName) &&
+            m_schema.isSingleValue(an_attribName))
+        {
+            throw new AttributeInUseException("A key for attribute "
+                + an_attribName + " already exists!") ;
+        }
+
+
+		String l_value = null ;
+
+		if(a_value.getClass().isArray()) {
+			l_value = new String((byte []) a_value) ;
+		} else {
+			l_value = (String) a_value ;
+		}
+
+		if(l_value.trim().equals("")) {
+			return ;
+		}
+
+		if(!m_schema.isValidSyntax(an_attribName, l_value)) {
+			throw new InvalidAttributeValueException("'" + l_value
+				+ "' does not comply with the syntax for attribute "
+				+ an_attribName) ;
+		}
+
+		put(an_attribName, l_value) ;
+    }
+
+
+    /**
+     * Removes the attribute/value pair in this Entry only without affecting
+     * other values that the attribute may have.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_value the value to remove
+     * @throws InvalidAttributeIdentifierException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValue(String an_attribName, Object a_value)
+        throws InvalidAttributeIdentifierException
+    {
+        if(!m_schema.hasAttribute(an_attribName)) {
+            throw new InvalidAttributeIdentifierException(an_attribName +
+                " is not a valid schema recognized attribute name.") ;
+        }
+
+		remove(an_attribName, a_value) ;
+    }
+
+
+    /**
+     * Removes all the attribute/value pairs in this Entry associated with the
+     * attribute.
+     *
+     * @param an_attribName attribute name/key
+     * @param an_attribName the value to remove
+     * @throws InvalidAttributeIdentifierException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValues(String an_attribName)
+        throws InvalidAttributeIdentifierException
+    {
+        if(!m_schema.hasAttribute(an_attribName)) {
+            throw new InvalidAttributeIdentifierException(an_attribName +
+                " is not a valid schema recognized attribute name.") ;
+        }
+
+        if(!containsKey(an_attribName)) {
+            return ;
+        }
+
+		remove(an_attribName) ;
+    }
+
+
+    /**
+     * Removes the specified set of attribute/value pairs in this Entry.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_valueArray the set of values to remove
+     * @throws InvalidAttributeIdentifierException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValues(String an_attribName, Object [] a_valueArray)
+        throws InvalidAttributeIdentifierException
+    {
+        if(!m_schema.hasAttribute(an_attribName)) {
+            throw new InvalidAttributeIdentifierException(an_attribName +
+                " is not a valid schema recognized attribute name.") ;
+        }
+
+		for(int ii = 0; ii < a_valueArray.length; ii++) {
+			remove(an_attribName, a_valueArray[ii]) ;
+		}
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/SingletonCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/SingletonCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,55 @@
+/*
+ * $Id: SingletonCursor.java,v 1.2 2003/03/13 18:27:01 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.NoSuchElementException ;
+
+
+/**
+ * An cursor that returns only one element! Used as annon inner class in so
+ * many places I had to create this one as well.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class SingletonCursor
+    extends Cursor
+{
+    private final Object m_singleton ;
+
+    public SingletonCursor(Object a_singleton)
+    {
+        m_singleton = a_singleton ;
+    }
+
+    /**
+     * Throws NoSuchElementException all the time.
+     */
+    public Object advance()
+    {
+        try { close() ; } catch(Exception e) {}
+        return m_singleton ;
+    }
+
+    /**
+     * Always returns false.
+     */
+    public boolean canAdvance()
+    {
+        return !isClosed() ;
+    }
+
+    /**
+     * Does nothing.
+     */
+    public void freeResources() { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/UnifiedBackend.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/UnifiedBackend.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,126 @@
+/*
+ * $Id: UnifiedBackend.java,v 1.13 2003/08/22 21:15:54 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend ;
+
+
+import java.util.Iterator ;
+
+import javax.naming.Name ;
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+import javax.naming.InvalidNameException ;
+import javax.naming.NameNotFoundException ;
+import javax.naming.ldap.LdapContext ;
+
+import org.apache.eve.schema.Schema ;
+
+
+/**
+ * Represents a composite backend nexus that forwards backend requests to the
+ * apropriate Backends registered with it.  UnifiedBackends are used to
+ * implement a name switch to get to the respective backend if one exists.
+ *
+ * Effectively, the Unified backend is a specific router interface in a system
+ * implementing the Router, (a.k.a. Request Router or Multiplexer) design
+ * pattern.  AtomicBackends are the channels which are added and removed using
+ * the register and unregister methods of the UnifiedBackend.  The routed
+ * messages are AtomicBackend interface calls.
+ */
+public interface UnifiedBackend
+	extends Backend
+{
+    /**
+     * Role of this service interface as mandated by the avalon framework.
+     */
+    public static final String ROLE = UnifiedBackend.class.getName() ;
+
+
+    /**
+     * Get's a Backend module by checking to see if a distinguished name
+     * contains the suffix of a backend as a prefix.  If no backend can be
+     * found for a valid DN an IllegalArgumentException is thrown or an
+     * InvalidNameException is thrown if the DN is not syntactically correct.
+     *
+     * @param a_dn the distinguished name potentially contained by the backend.
+     * @return the Backend that would contain the entry if it were to exist.
+     * @throws InvalidNameException if a_dn is syntactically incorrect.
+     * @throws NameNotFoundException if no backend can house the
+     * hypothetical entry - it is not within the namespace of the federated
+     * backends.
+     * @deprecated we would like to deprecate this method because we would no
+     * longer like to expose it to the outside world which could misuse it
+     * without providing the required dn in normalized form.
+     */
+    AtomicBackend getBackend(Name a_dn)
+        throws NamingException ;
+
+
+    /**
+     * Gets the most significant Dn that exists within the server and hence can
+     * be matched to an actual entry.
+     *
+     * @param a_dn to use for the matching test.
+     * @return the matching portion of a_dn, or the valid empty string dn if no
+     * match was found.
+     */
+    Name getMatchedDn( Name a_dn )
+        throws NamingException, BackendException ;
+
+    /**
+     * Gets an iteration over the Backends managed by this BackendManager.
+     *
+     * @return the iteration over Backend instances.
+     */
+    Iterator listBackends() ;
+
+    /**
+     * Gets an iteration over the suffixes of the Backends managed by this
+     * UnifiedBackend.
+     *
+     * @return the iteration over Backend suffix names as Strings.
+     */
+    Iterator listSuffixes() ;
+
+    Schema getSchema(Name a_dn)
+        throws NamingException ;
+
+    NameParser getNormalizingParser() ;
+
+    NameParser getNameParser() ;
+
+    NameParser getNormalizingParser(Name a_dn)
+        throws NamingException ;
+
+    Name getNormalizedName(String a_name)
+        throws NamingException ;
+
+    Name getName(String a_name)
+        throws NamingException ;
+
+	RootDSE getRootDSE() ;
+
+	/**
+     * Registers a Backend with this BackendManager.  Called for each Backend
+     * implementation after it is started.  This is the only way it will receive
+     * requests from the protocol server.
+     *
+     * @param a_backend Backend component to register with this manager.
+     */
+    void register(AtomicBackend a_backend) ;
+
+    /**
+     * Unregisters a Backend with this BackendManager.  Called for each
+     * registered Backend right befor it is to be stopped.  This prevents
+     * protocol server requests from reaching the Backend.
+     *
+     * @param a_backend Backend component to unregister with this manager.
+     */
+    void unregister(AtomicBackend a_backend) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/backendhowto.html
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/backendhowto.html	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>Backend HOWTO</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+Work in progress . . . 
+</body>
+</html>

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/contract.html
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/contract.html	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,237 @@
+<html>
+<head>
+<title>Server Backend Contract</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+<p><font color="#999999">$Id: contract.html,v 1.1.1.1 2002/11/13 23:46:12 akarasulu Exp $</font> </p>
+<h2 align="center">Server Backend Contract</h2>
+<p>The Server Backend Contract is defined syntactically by the APIs presented 
+  in the backend package. Semantic contracts are also required to make sure that 
+  Backends operate as expected and as efficiently as possible.</p>
+<p>&nbsp;</p>
+<h3 align="center">Syntax Overview</h3>
+<p>Backends are interfaces to an entry backing store. Backends provide create, 
+  read, update and delete (CRUD) operations, against the store. Bulk retreivals 
+  using filtered searches and heirarchical (parent child) relationships must also 
+  be provided. </p>
+<p>Backends are the factories for BackendArtifacts. Together, the Backend interface 
+  and these artifacts specify how entries and their attributes are accessed, created 
+  and modified both individually and in bulk.</p>
+<p>&nbsp;</p>
+<h4>CRUD &amp; Entry Life-Cycle Operations</h4>
+<p>The operations used to manipulate entries use the <b>CRUD</b> model which dictates 
+  the Entry life-cycle. These Backend interface methods are straight forward:</p>
+<ul>
+  <li><code>newEntry(String a_dn):Entry</code></li>
+  <li><font color="#FF0000"><code><b><u>c</u></b></code></font><code>reate(Entry 
+    an_entry):void</code></li>
+  <li><code><b><u><font color="#FF0000">r</font></u></b>ead(String a_dn):Entry</code></li>
+  <li><code><b><u><font color="#FF0000">u</font></u></b>pdate(Entry an_entry):void</code></li>
+  <li><code><b><u><font color="#FF0000">d</font></u></b>elete(Entry an_entry):void</code></li>
+</ul>
+<p>Perhaps the only method worthy of explanation is <code>newEntry</code>. This 
+  method constructs a new empty and invalid Entry instance. Valid entries exist 
+  within the Backend's backing store and invalid entries do not: they have been 
+  instantiated yet <code>create</code> has not been called on the Entry. Backends 
+  are Entry factories in this respect. An invalid Entry merely contains the user 
+  provide DN string as an operational attribute and the <a href="dnnormalization.html">normalized</a> 
+  string stored as a property of the class. These <b>CRUD</b> methods do the obvious 
+  once the ball is set in motion. Newly instantiated entries are altered via Entry 
+  interface methods and added to the Backend using the <code>create</code> method. 
+  Once created the Entry can have attributes manipulated and can be used to make 
+  successful calls to <code>delete</code>, and <code>update</code> (presuming 
+  schema constraints are not violated). Calls to <code>read</code> will return 
+  created and updated entries. These interfaces are simple and straight forward. 
+  The rest of the Backend interface methods can be categorized as non-<b>CRUD</b> 
+  methods belonging to the set of entry checker methods, hierarchical operations, 
+  or search operations:</p>
+<p>Entry Test Methods:</p>
+<ul>
+  <li><code>hasEntry(String a_dn):boolean</code></li>
+  <li><code>isSuffix(Entry an_entry):boolean</code></li>
+</ul>
+<p>Hierarchical Operations:</p>
+<ul>
+  <li><code>getParent(String a_childDN):Entry</code></li>
+  <li><code>listChildren(String a_parentDN):Cursor</code></li>
+</ul>
+<p>Search Operations:</p>
+<ul>
+  <li><code>search(String a_base, String a_filter, SearchControls a_ctls):Cursor</code></li>
+</ul>
+<p>The Backend is responsible for enforcing Schema constraints. Separate Schema 
+  interfaces dictate the interaction between Backend and Schema subsystems. Hence 
+  schema based attribute normalization and schema based objectclass constraint 
+  checking are delegated to the Schema subsystem by the Backend. This dependency 
+  is the source of the various kinds of NamingExceptions thrown by most of the 
+  methods on the Backend interface. A Backend simply let's these exceptions pass 
+  through.</p>
+<p>&nbsp;</p>
+<h4>BackendArtifacts: Helper Interfaces</h4>
+<p>An Entry is a pivotal helper class and a Backend artifact. It represents a 
+  server side LDAP entry by containing attributes. It is the atomic unit of storage 
+  within a Backend. In this respect an Entry is a value object. Once instantiated 
+  by a Backend using the <code>newEntry</code> call, attribute value pair add 
+  methods are used to add single and multivalued attributes to new instances. 
+  Once all attributes are added the Entry can be stored in the Backend via <code>create</code>. 
+  Change and remove mutators are used afterwords on the validated Entry to alter 
+  its attributes. An Entry can be repeatedly updated this way until it is deleted. 
+  Backends and cursors provide the means to access and store entries while entries 
+  provide the means to alter attributes.</p>
+<p>Cursor artifacts extend the Backend interfaces to provide search and bulk access 
+  methods to efficiently iterate over entries. In very large DIBs entries cannot 
+  be loaded on mass due to resource limitations. Likewise search implementations 
+  must manage joins efficiently avoiding mass retreivals or table scans returning 
+  results on an as needed basis. Cursor are the iterative conduit into the DIB.</p>
+<p>The Cursor class is abstract and implemented as a NamingEnumeration that extends 
+  the Observable class. Cursors will interface with the Backend factory that created 
+  it. Most interfaces on Backends could potentially throw various subclasses of 
+  NamingException. It was natural to encapsulate all possible naming exceptions 
+  by implementing a NamingEnumeration. Observable was extended to potentially 
+  anounce open/close state changes to managing Backends so resouces associated 
+  with Cursors can be freed. The Backend interface does not extend Observable 
+  however. Not all backends will need to 'observe' these state changes. Implementations 
+  may decide to complement Cursor Observables by implementing the Observer interface, 
+  the potential is there if its use is needed. Also subtype interfaces of Backend, 
+  namely Atomic Backend and Unified Backend are designed to be used as service 
+  interfaces in the avalon framework. The design pattern could be compromised 
+  if the Observer's update method were to be exposed as a service interface.</p>
+<p>The abstract Cursor class declares the NamingException methods final and introduces 
+  the abstract protected advance, canAdvance, and freeResources methods requiring 
+  their implementation by concrete Cursors. These seals were introduced to allow 
+  the abstract Cursor class to automatically close itself without the chance of 
+  tampering by subclasses. When exhausted or when exceptions prevent further iteration, 
+  Cursors call close. Enumeration and NamingEnumeration semantics are maintained 
+  by wraping unexpected Backend exceptions in a subtype of NoSuchElement exception 
+  called CursorException. The JDK expects such an exception to be thrown when 
+  nextElement and next are called on exhausted instances of these interfaces.</p>
+<p>&nbsp;</p>
+<h3 align="center">Server Backend Semantics</h3>
+<p>Some operational semantics are supported by the syntax of classes and interfaces 
+  defined in the backend package. Others are not and need to be explicitly defined 
+  here. Exception handling semantics and iterative cursor behavoir are aspects 
+  of expected semantics in the server backend contract.</p>
+<p>&nbsp;</p>
+<h4>Exception Handling</h4>
+<p>To allow the gambit of Backend implementations, while balancing complexity 
+  with performance we quickly realized that most effective Backends must interface 
+  with a Schema subsystem. Attribute value and DN normalization will be a concern 
+  for every Backend. This is unavoidable. Attribute value normalization is specific 
+  to the type of the attribute and hence is dependent upon schema information.</p>
+<p>Value normalization requires valid values and introduces schema checking issues: 
+  object class correctness, attribute syntax correctness, attribute value syntaxes 
+  and matching rules. There simply is no way to avoid these aspects however they 
+  can and will be encapsulated within schema subsystem components provided to 
+  all backends as an independent service. Backends interface with the schema subsystem 
+  through Schemas and attribute Normalizer interfaces to conduct schema checking 
+  and validation. These interfaces will throw NamingException subclasses to announce 
+  schema violations. Backends need to remain as simple as possible. Minimizing 
+  the amount of exception handling within backends to manage calls to Schema and 
+  Normalizer interfaces keeps the complexity down. For these reasons many methods 
+  on backend package classes and interfaces throw subclasses of NamingExceptions. 
+  Hence Backends and their artifacts pass through exceptions generated by schema 
+  method calls. </p>
+<p>Backend implementations need not handle NamingExceptions generated by calls 
+  to dependent schema APIs. All Backends hence will need to have access to the 
+  schema subsystem. The backend package does not define how this actually happens 
+  nor does it place any restriction on the means. This is due to the use of various 
+  server composition schemes: embedded, standalone and micro-kernel configurations. 
+  Handling naming subsystem, schema subsystem and BackendException failures are 
+  the responsibility of protocol processing elements which sit above these modules 
+  in their various configurations.</p>
+<p>Exception bubble up from schema subsystem calls. The types of exceptions generated 
+  by the various interfaces hint at what they do. We have tried to distribute 
+  the number of exception types thrown by interfaces based on aspect. Some naming 
+  exceptions will result when validating the correctness of attribute values using 
+  attribute syntaxes and their identifiers. Others result in Entry level schema 
+  violations where the required attributes in an objectclass definition as missing 
+  or extra attributes not allowed by the schema have been added. We will coin 
+  the phrase entry level and attribute level to describe the two diffent types 
+  of violations we must manage. The Backend interface must manage entry level 
+  violations first because it is the facade through which all entries are created, 
+  updated and deleted. Secondly, restrictions on entry attribute composition cannot 
+  be managed by an Entry. Think about what would happend as an entry is being 
+  built. Stages in building it would of course be inconsistent with schema requirements 
+  on objectclasses. When an objectclass attribute is added the Entry is already 
+  inconsistent if that objectclass has manditory attribute requirements. What 
+  do you add first the objectclass attribute or the attributes it requires to 
+  be consistent with the objectclass definition? If the attributes required are 
+  added first they violate the schema by not having the appropriate objectclass 
+  attribute. To avoid this chicken or egg problem such Entry level schema checking 
+  is delegated to the Backend interfaces and avoided by Entry interfaces. Hence 
+  the contract presumes that Backend implementations manage objectclass schema 
+  checks while Entry implementations for that Backend manage attribute schema 
+  checks. </p>
+<p>Other non-schema subsystem associated exceptions (also NamingException subclasses) 
+  are thrown by the search method. These exceptions express problems with search 
+  criteria. Cursors created by searches can also throw other exceptions associated 
+  with resources or search limitations. These matters are left to the discretion 
+  of the backend implementors. Below we categorically list some of the exceptions 
+  that could be thrown by backend implementation classes which have conveniently 
+  been defined for us by the JNDI packages. Note that some exceptions in JNDI 
+  were defined specifically to express client side or client side provider errors. 
+  If we elect to use them we refer to them in our own serverside context.</p>
+<p><b>Cursor: </b></p>
+<p>Search errors (implicitly defined as NamingExceptions)</p>
+<ul>
+  <li>CannotProceedException</li>
+  <li>InterruptedNamingException</li>
+  <li>LimitExceededException</li>
+  <li>LinkException</li>
+  <li>LinkLoopException</li>
+  <li>MalformedLinkException</li>
+  <li>PartialResultException</li>
+  <li>SizeLimitExceededException</li>
+  <li>TimeLimitExceededException</li>
+</ul>
+<h4>Backend: </h4>
+<p> Objectclass level schema violations (explicitly thrown)</p>
+<ul>
+  <li>NameNotFoundException</li>
+  <li>InvalidNameException</li>
+  <li>NameAlreadyBoundException</li>
+  <li>ContextNotEmptyException</li>
+  <li>InvalidSearchFilterException</li>
+  <li>InvalidSearchControlsException</li>
+  <li>InvalidAttributesException</li>
+  <li>SchemaViolationException<br>
+  </li>
+</ul>
+<h4>Entry: </h4>
+Attribute level schema violations (explicitly thrown) 
+<ul>
+  <li>AttributeModificationException</li>
+  <li>InvalidAttributeValueException</li>
+  <li>InvalidAttributeIdentifierException</li>
+</ul>
+<p>&nbsp;</p>
+<h4>Cursor Behavoir</h4>
+<p>Cursors react to exceptional conditions based on the iteration methods used. 
+  If Cursors are used as Enumerations callers are sheilded from exception handling. 
+  Both backend and naming exceptions are logged and the Cursor is automatically 
+  closed if the hasNextElement method bombs. The nextElement method logs then 
+  transduces NamingExceptions and BackendExceptions into a CursorException which 
+  is a subclass of NoSuchElementException. Implementations must support the Enumeration 
+  contract by making sure that calls to nextElement preceded by hasNextElement 
+  call with a true return value never throw a CursorException. This can be accomplished 
+  by prefetching values.</p>
+<p>A similar contract is required for NamingEnumeration interfaces. The hasNext 
+  method sheilds callers from handling Backend exceptions while allowing them 
+  to handle NamingExceptions. BackendExceptions when encountered are logged and 
+  the Cursor is closed. Likewise the next method allows callers to handle NamingExceptions, 
+  yet sheilds them from BackendExceptions resulting from delegated calls to advance. 
+  It logs the BackendException and rethrows it as a CursorException. Again NamingEnumeration 
+  semantics must be adhered to. Calls to next should not throw a CursorException 
+  if hasNext returned true before the call. Prefetching again is the key.</p>
+<p>Concrete Cursor implementors may wonder how they can comply with the Enumeration 
+  and NamingEnumeration contract if all their interface methods are made final 
+  by the abstract Cursor class. Again prefetching is the key! Cursor implementors 
+  should prefetch at Cursor initialization. If the prefetch fails the BackendException 
+  can be handled by the caller to the Backend interface method instantiating the 
+  Cursor. If the prefetch yeilds no result a closed exhausted Cursor is returned. 
+  They are empty in such cases and the contract is satisfied.</p>
+<p>&nbsp;</p>
+</body>
+</html>

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/dnnormalization.html
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/dnnormalization.html	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,63 @@
+<html>
+<head>
+<title>LDAP &amp; X.500 Distinguished Name Normalization</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+<p><font color="#999999">$Id: dnnormalization.html,v 1.1.1.1 2002/11/13 23:46:12 akarasulu Exp $</font></p>
+<h2 align="center">LDAP &amp; X.500 Distinguished Name Normalization</h2>
+
+<p>Distinguished names as specified by <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 
+  2253</a> or <a href="http://www.ietf.org/rfc/rfc1779.txt">RFC 1779</a> (obsoleted 
+  by 2253) should be normalized for Backend storage when used as keys. Without 
+  normalization equality matching against inconsistant user formated strings will 
+  fail miserably. Several articals and forums have debated how the normalization 
+  should proceed. In the 1.4 JDK a new X500Principal class handles normalization 
+  of distinguished names from a String representation and an BER encoder ASN.1 
+  representation. SUN describes it better than I can in the Javadocs for <a href="http://java.sun.com/j2se/1.4/docs/api/javax/security/auth/x500/X500Principal.html#getName(java.lang.String)">X500Principal</a>. 
+</p>
+<p>The Naming subsystem of our server shall use such a class or define it's own 
+  canonicalization of the distinguished name. The best bet is to use X500Principal 
+  yet there might be an advantage to making this aspect a pluggable feature since 
+  many ways exist and arguments over the matter are still unsettled.</p>
+<p>Regardless of the means used to generate DN keys (normalized DNs) the original 
+  user provided formating of the DN at creation or modification time shall be 
+  preserved under the Entry's attributes or its operational attributes depending 
+  on what DN we are refering to. So when we return the entry to the user it is 
+  formatted exactly in the way the user provided the DN in the first place. Some 
+  operational DN attributes managed by either the Backend or the naming subsystem 
+  of the server will be kept in normalized form.</p>
+<p>Backends receive entries for creation starting with the suffix or root Entry 
+  of their Directory Information Base (DIB). Operational keyed DNs must be provided 
+  in normalized and user provided formats. Other non-operational or administrative 
+  attributes may need normalization based on their specific attribute syntax if 
+  they are indexed: presuming the backend manages indices. The Backend must interface 
+  with both the schema subsystem and an attribute syntax specific normalizer to 
+  generate the appropriate normalized keys in canonical form for these attribute 
+  indices.</p>
+<p>Matching rules, attribute syntax, and attribute type information is required 
+  to correctly normalize attributes. For example case sensitive strings can not 
+  be case normalized (i.e. all lower cased) for use as keys. If case sensitive 
+  strings are case normalized we would not be able to store things like Unix file 
+  names: Notes.txt and notes.txt could not exist as separate files within a common 
+  directory. Because schema information is required to format/normalize/canonicalize 
+  attribute values for key representation the normalization functionality should 
+  be provided by either the Schema subsystem or by a Normalizer component that 
+  is dependent on the Schema subsystem or rather generated/provided by it. Figure 
+  1 shows how the intramodule dependencies would look:</p>
+<p><img src="NormalizerComponent.gif" width="601" height="168"></p>
+<p>The Backend subsystems would be dependent on components and interfaces within 
+  the schema subsystem. Normalizers will obviously be dependent on the nature 
+  of the attribute so the SchemaModule would provide access to one based on an 
+  attribute type via the Schema interface. A Backend would be provided a handle 
+  to the Schema subsystem by the server at some point in the module's lifecycle. 
+  The Backend in it's solid state would ask the SchemaModule for its Schema using 
+  its suffix as a parameter. The module would return the appropriate schema for 
+  that Backend. The Backend would then proceed to ask the Schema for an attribute 
+  specific Normalizer by providing the name of the attribute as a parameter to 
+  a getNormalizer method on the Schema interface. The Normalizer would then be 
+  used to generate a normalized attribute value from the user provided attribute 
+  value which can now be used by the Backend as a key.</p>
+</body>
+</html>

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/Database.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/Database.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,233 @@
+/*
+ * $Id: Database.java,v 1.4 2003/03/13 18:27:14 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import javax.naming.Name ;
+import java.util.Iterator ;
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.backend.BackendException ;
+
+import org.apache.eve.backend.jdbm.index.Index ;
+import org.apache.eve.backend.jdbm.index.IndexCursor;
+import org.apache.eve.backend.Cursor ;
+
+import org.apache.regexp.RE ;
+import org.apache.commons.collections.MultiMap ;
+import org.apache.avalon.framework.logger.Logger;
+
+
+/**
+ *
+ */
+public interface Database
+{
+    public Schema getSchema() ;
+
+    //////////////////////
+    // Index Operations //
+    //////////////////////
+
+    public void addIndexOn(String an_attribute)
+        throws BackendException, NamingException ;
+
+    public boolean hasIndexOn(String an_attribute) ;
+
+    public Index getIndex(String an_attribute)
+        throws IndexNotFoundException ;
+
+    public BigInteger getEntryId(String a_dn)
+        throws BackendException, NamingException ;
+
+    public String getEntryDn(BigInteger a_id)
+        throws BackendException ;
+
+    public BigInteger getParentId(String a_dn)
+        throws BackendException, NamingException ;
+
+    public BigInteger getParentId(BigInteger a_childId)
+        throws BackendException ;
+
+    public int count()
+        throws BackendException ;
+
+    public int getIndexScanCount(String an_attribute)
+        throws BackendException, NamingException ;
+
+    public int getIndexScanCount(String an_attribute, String a_value)
+        throws BackendException, NamingException ;
+
+    public int getIndexScanCount(String an_attribute, String a_value,
+        boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public boolean assertIndexValue(String an_attribute, Object a_value,
+	    BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public boolean assertIndexValue(String an_attribute, Object a_value,
+	    BigInteger a_id, boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getIndexCursor(String an_attribute)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getIndexCursor(String an_attribute, String a_value)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getIndexCursor(String an_attribute, String a_value,
+        boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getIndexCursor(String an_attribute, RE a_regex)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getIndexCursor(String an_attribute, RE a_regex,
+        String a_prefix)
+        throws BackendException, NamingException ;
+
+    //////////////////////////////////
+    // Master Table CRUD Operations //
+    //////////////////////////////////
+
+    public void create(LdapEntryImpl an_entry, BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public LdapEntryImpl read(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public void update(LdapEntryImpl an_entry)
+        throws BackendException, NamingException ;
+
+    public void delete(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    /////////////////////////////
+    // Parent/Child Operations //
+    /////////////////////////////
+
+    public Cursor getChildren(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public int getChildCount(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public Name getSuffix() ;
+
+    public LdapEntryImpl getSuffixEntry()
+        throws BackendException, NamingException ;
+
+    public BigInteger getNextId()
+        throws BackendException ;
+
+    public BigInteger getCurrentId()
+        throws BackendException ;
+
+    public void sync() ;
+
+    public void close() ;
+
+    /////////////////////
+    // Utility Methods //
+    /////////////////////
+
+
+    public void setProperty(String a_propertyName, String a_propertyValue)
+        throws BackendException ;
+
+    public String getProperty(String a_propertyName)
+        throws BackendException ;
+
+    /**
+     * Lists only the User Defined Index (UDI) Attributes.
+     */
+    public Iterator getUDIAttributes() ;
+
+    public final static String [] SYS_INDICES =
+    { Schema.DN_ATTR, Schema.EXISTANCE_ATTR, Schema.HIERARCHY_ATTR} ;
+
+    /**
+     * Gets the names of the maditory system indices used by the database.
+     * These names are used as the [operational] 'attribute' or key names
+     * of the indices.  All cursor operations and assertion operations use
+     * these names to select the appropriate UDI (User Defined Index) or SDI
+     * (System Defined Index) to operate upon.
+     */
+	public String [] getSystemIndices() ;
+
+    public MultiMap getIndices(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    /**
+     * Modifies the relative distinguished name (RDN) of an entry
+     * without changing any parent child relationships.  This call
+     * has the side effect of altering the distinguished name of
+     * descendent entries if they exist.  The boolean argument will
+     * optionally remove the existing RDN attribute value pair
+     * replacing it with the new RDN attribute value pair.  If other
+     * RDN attribute value pairs exist besides the current RDN they
+     * will be spared.
+     *
+     * @param an_entry the entry whose RDN is to be modified.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void modifyRdn(org.apache.eve.backend.jdbm.LdapEntryImpl an_entry,
+        String a_newRdn, boolean a_deleteOldRdn)
+	    throws BackendException, NamingException ;
+
+    /**
+     * This overload combines the first two method operations into one.
+     * It changes the Rdn and the parent prefix at the same time while
+     * recursing name changes to all descendants of the child entry. It
+     * is obviously more complex than the other two operations alone and
+     * involves changes to both parent child indices and DN indices.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move(LdapEntryImpl a_parentEntry, LdapEntryImpl a_childEntry,
+	    String a_newRdn, boolean a_deleteOldRdn)
+	    throws BackendException, NamingException ;
+
+    /**
+     * Moves a child entry without changing the RDN under a new parent
+     * entry.  This effects the parent child relationship between the
+     * parent entry and the child entry.  The index for the child
+     * mapping it to the current parent is destroyed and a new index
+     * mapping it to the new parent is created.  As a side effect the
+     * name of the child entry and all its descendants will reflect the
+     * move within the DIT to a new parent.  The old parent prefix to
+     * the distinguished names of the child and its descendents will be
+     * replaced by the new parent DN prefix.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move(LdapEntryImpl a_parentEntry, LdapEntryImpl a_childEntry)
+	    throws BackendException, NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/EntryCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/EntryCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,66 @@
+/*
+ * $Id: EntryCursor.java,v 1.3 2003/03/13 18:27:14 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.index.IndexRecord ;
+
+import javax.naming.NamingException ;
+
+/**
+ * @testcase org.apache.eve.backend.jdbm.TestEntryCursor 
+ */
+public class EntryCursor
+    extends Cursor
+{
+	protected final JdbmModule m_backend ;
+    protected final Cursor m_cursor ;
+
+    /**
+     * Creates a cursor over all the elements in the table.  The key will change
+     * to represent the value of key pointed to by this cursor.
+     *
+     * @param a_table Db to iterate over.
+     * @throws DbException if something goes drastically wrong.
+     */
+    public EntryCursor(JdbmModule a_backend, Cursor a_cursor)
+    {
+		m_cursor = a_cursor ;
+        m_backend = a_backend ;
+    }
+
+
+    protected Object advance()
+        throws BackendException, NamingException
+    {
+		IndexRecord l_rec = (IndexRecord) m_cursor.next() ;
+        return m_backend.read(l_rec.getEntryId()) ;
+    }
+
+
+    protected boolean canAdvance()
+        throws BackendException, NamingException
+    {
+		return m_cursor.hasMore() ;
+    }
+
+
+    protected void freeResources()
+    {
+        try {
+            m_cursor.close() ;
+        } catch (Exception e) {
+            e.printStackTrace() ;
+            getLogger().error("While closing underlying IndexCursor: ", e) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/IndexNotFoundException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/IndexNotFoundException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,63 @@
+/*
+ * $Id: IndexNotFoundException.java,v 1.2 2003/03/13 18:27:15 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import org.apache.eve.backend.BackendException ;
+
+
+public class IndexNotFoundException
+    extends BackendException
+{
+    public final String m_indexName ;
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param a_message The message associated with the exception.
+     */
+    public IndexNotFoundException(String a_indexName)
+    {
+        super("Cannot efficiently search the DIB w/o an index on attribute "
+            + a_indexName + "\n. To allow such searches please contact the "
+            + "directory\nadministrator to create the index or to enable "
+            + "referals on searches using these\nattributes to a replica with "
+            + "the required set of indices.") ;
+        m_indexName = a_indexName ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param a_message The message associated with the exception.
+     */
+    public IndexNotFoundException(String a_message, String a_indexName)
+    {
+        super(a_message) ;
+        m_indexName = a_indexName ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message and an error.
+     * @param a_message The message associated with the exception.
+     */
+    public IndexNotFoundException(String a_message, String a_indexName,
+        Throwable a_throwable)
+    {
+        super(a_message, a_throwable) ;
+        m_indexName = a_indexName ;
+    }
+
+
+    public String getIndexName()
+    {
+        return m_indexName ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmDatabase.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmDatabase.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,1049 @@
+/*
+ * $Id: JdbmDatabase.java,v 1.12 2003/08/06 03:01:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Collection ;
+
+import javax.naming.Name ;
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+
+import java.io.File ;
+import java.io.IOException ;
+
+import java.math.BigInteger ;
+import java.text.ParseException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.schema.Normalizer ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.index.Index ;
+import org.apache.eve.backend.jdbm.index.JdbmIndex ;
+import org.apache.eve.backend.jdbm.index.IndexRecord ;
+import org.apache.eve.backend.jdbm.table.MasterTable ;
+import org.apache.eve.backend.jdbm.index.IndexCursor ;
+
+import org.apache.regexp.RE ;
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+
+import org.apache.commons.collections.MultiMap ;
+import org.apache.commons.collections.MultiHashMap ;
+
+import org.apache.ldap.common.name.DnParser ;
+import org.apache.ldap.common.util.NamespaceTools ;
+
+import jdbm.recman.RecordManager ;
+
+
+/**
+ * No caching just coordinated maintance of indices on CRUD operations for
+ * LdapEntrys in a BerkeleyDatabase.  This is not a module but a component
+ * used by the Berkeley Db Backend Module.
+ * @testcase <{TestDatabase}>
+ */
+public class JdbmDatabase
+    extends AbstractLogEnabled
+    implements Database
+{
+	public static boolean debug = true ;
+
+    public Logger log ;
+    private final RecordManager m_recMan ;
+    private final Name m_suffix ;
+    private final String m_wkdir ;
+    private final Schema m_schema ;
+    private final MasterTable m_master ;
+    private final JdbmIndex m_nameIdx ;
+    private final JdbmIndex m_existanceIdx ;
+    private final JdbmIndex m_hierarchyIdx ;
+    private final Map m_indices ;
+
+    private NameParser m_nonNormalizingParser = null ;
+    private final NameParser m_parser ;
+
+
+    public JdbmDatabase(final Schema a_schema,
+        final Name a_suffix,
+        final String a_wkdirPath)
+        throws BackendException, NamingException
+    {
+        m_schema = a_schema ;
+        m_suffix = a_suffix ;
+        m_wkdir = a_wkdirPath ;
+
+        m_parser = m_schema.getNormalizingParser() ;
+        try {
+            m_nonNormalizingParser = new DnParser() ;
+        } catch(IOException e) {
+            throw new BackendException("Could not initialize the non-" +
+                "normalizing DnParser", e) ;
+        }
+
+        try {
+            m_recMan = new RecordManager(a_wkdirPath
+                + File.separator + "master") ;
+            m_recMan.disableTransactions() ;
+        } catch(IOException e) {
+            String l_msg = "Could not initialize RecordManager:\n"
+                + ExceptionUtil.printStackTrace(e) ;
+            throw new BackendException(l_msg, e) ;
+        }
+
+        m_master = new MasterTable(m_recMan) ;
+        m_nameIdx = new JdbmIndex(Schema.DN_ATTR, m_schema, m_wkdir) ;
+        m_existanceIdx =
+            new JdbmIndex(Schema.EXISTANCE_ATTR, m_schema, m_wkdir) ;
+        m_hierarchyIdx =
+            new JdbmIndex(Schema.HIERARCHY_ATTR, m_schema, m_wkdir) ;
+        m_indices = new HashMap() ;
+    }
+
+
+    public Schema getSchema()
+    {
+        return m_schema ;
+    }
+
+
+    //////////////////////
+    // Index Operations //
+    //////////////////////
+
+
+    public void addIndexOn(String an_attribute)
+        throws BackendException, NamingException
+    {
+        an_attribute = an_attribute.toLowerCase() ;
+        if(m_schema.isBinary(an_attribute)) {
+            throw new BackendException(
+                "Indices not allowed on binary attributes!") ;
+        }
+
+        Normalizer l_normalizer = m_schema.getNormalizer(an_attribute, true) ;
+
+        if(null == l_normalizer) {
+            throw new BackendException("Cannot create index on attribute "
+                + an_attribute + " when schema does not have a normalizer for "
+                + "attribute " + an_attribute) ;
+            
+        }
+
+        an_attribute = an_attribute.toLowerCase() ;
+        JdbmIndex l_index = new JdbmIndex(an_attribute, m_schema, m_wkdir) ;
+        l_index.enableLogging(super.getLogger()) ;
+        m_indices.put(an_attribute, l_index) ;
+    }
+
+
+    public boolean hasIndexOn(String an_attribute)
+    {
+        try {
+            Index l_index = getIndex(an_attribute) ;
+            return l_index != null ;
+        } catch(IndexNotFoundException e) {
+            return false ;
+        }
+    }
+
+
+    public Index getIndex(String an_attribute)
+        throws IndexNotFoundException
+    {
+        String l_lowerCased = an_attribute.toLowerCase() ;
+
+        if(m_indices.containsKey(an_attribute)) {
+            return (Index) m_indices.get(an_attribute) ;
+        } else if(m_indices.containsKey(l_lowerCased)) {
+            return (Index) m_indices.get(l_lowerCased) ;
+        } else if(an_attribute.equals(Schema.DN_ATTR)) {
+            return m_nameIdx ;
+        } else if(an_attribute.equals(Schema.EXISTANCE_ATTR)) {
+            return m_existanceIdx ;
+        } else if(an_attribute.equals(Schema.HIERARCHY_ATTR)) {
+            return m_hierarchyIdx ;
+        } else {
+            throw new IndexNotFoundException("An index on attribute " +
+                an_attribute + " does not exist!") ;
+        }
+    }
+
+
+    public BigInteger getEntryId(String a_dn)
+        throws BackendException, NamingException
+    {
+        return m_nameIdx.getForward(a_dn) ;
+    }
+
+
+    public String getEntryDn(BigInteger a_id)
+        throws BackendException
+    {
+        return (String) m_nameIdx.getReverse(a_id) ;
+    }
+
+
+    public BigInteger getParentId(String a_dn)
+        throws BackendException, NamingException
+    {
+        BigInteger l_childId = m_nameIdx.getForward(a_dn) ;
+        return (BigInteger) m_hierarchyIdx.getReverse(l_childId) ;
+    }
+
+
+    public BigInteger getParentId(BigInteger a_childId)
+        throws BackendException
+    {
+        return (BigInteger) m_hierarchyIdx.getReverse(a_childId) ;
+    }
+
+
+    public int count()
+        throws BackendException
+    {
+        return m_master.count() ;
+    }
+
+
+    public int getIndexScanCount(String an_attribute)
+        throws BackendException, NamingException
+    {
+        return getIndex(an_attribute).count() ;
+    }
+
+
+    public int getIndexScanCount(String an_attribute, String a_value)
+        throws BackendException, NamingException
+    {
+        return getIndex(an_attribute).count(a_value) ;
+    }
+
+
+    public int getIndexScanCount(String an_attribute, String a_value,
+        boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+        return getIndex(an_attribute).count(a_value, isGreaterThan) ;
+    }
+
+
+    public boolean assertIndexValue(String an_attribute, Object a_value,
+	    BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        return getIndex(an_attribute).hasValue(a_value, a_id) ;
+    }
+
+
+    public boolean assertIndexValue(String an_attribute, Object a_value,
+	    BigInteger a_id, boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+        return getIndex(an_attribute).hasValue(a_value, a_id, isGreaterThan) ;
+    }
+
+
+    public IndexCursor getIndexCursor(String an_attribute)
+        throws BackendException, NamingException
+    {
+	    return getIndex(an_attribute).getCursor() ;
+    }
+
+
+    public IndexCursor getIndexCursor(String an_attribute, String a_value)
+        throws BackendException, NamingException
+    {
+	    return getIndex(an_attribute).getCursor(a_value) ;
+    }
+
+
+    public IndexCursor getIndexCursor(String an_attribute, String a_value,
+        boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+	    return getIndex(an_attribute).getCursor(a_value, isGreaterThan) ;
+    }
+
+
+    public IndexCursor getIndexCursor(String an_attribute, RE a_regex)
+        throws BackendException, NamingException
+    {
+	    return getIndex(an_attribute).getCursor(a_regex) ;
+    }
+
+
+    public IndexCursor getIndexCursor(String an_attribute, RE a_regex,
+        String a_prefix)
+        throws BackendException, NamingException
+    {
+	    return getIndex(an_attribute).getCursor(a_regex, a_prefix) ;
+    }
+
+
+    //////////////////////////////////
+    // Master Table CRUD Operations //
+    //////////////////////////////////
+
+
+    public void create(LdapEntryImpl an_entry, BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        String l_ldif = m_schema.getLdifComposer().compose(an_entry) ;
+        m_master.put(l_ldif, a_id) ;
+        addIndices(an_entry) ;
+        an_entry.validate() ;
+    }
+
+
+    public LdapEntryImpl read(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        LdapEntryImpl l_entry = new LdapEntryImpl(this.m_schema) ;
+        l_entry.enableLogging(getLogger()) ;
+
+        String l_ldif = m_master.get(a_id) ;
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("JdbmDatabase.read(BigInteger): Extracted the "
+                + "following LDIF from the master table:\n" + l_ldif) ;
+        }
+
+        try {
+            m_schema.getLdifParser().parse(l_entry, l_ldif) ;
+        } catch(ParseException e) {
+            throw new BackendException("Database may be corrupt.  Cannot "
+                + "parse ldif entries in backing store.", e) ;
+        }
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("JdbmDatabase.read(BigInteger): Resusitated the "
+                + "following entry using the ldif parser:\n" + l_entry) ;
+        }
+
+        l_entry.validate() ;
+        return l_entry ;
+    }
+
+
+    public void update(LdapEntryImpl an_entry)
+        throws BackendException, NamingException
+    {
+        String l_ldif = m_schema.getLdifComposer().compose(an_entry) ;
+        m_master.put(l_ldif, an_entry.getEntryID()) ;
+        updateIndices(an_entry) ;
+        an_entry.validate() ;
+    }
+
+
+    public void delete(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("JdbmDatabase.delete(BigInteger): "
+                + "Deleting entry with id " + a_id) ;
+        }
+
+        LdapEntryImpl l_entry = read(a_id) ;
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("JdbmDatabase.delete(BigInteger): "
+                + "Resusitated entry for deletion " + l_entry) ;
+        }
+
+        dropIndices(l_entry) ;
+        m_master.del(a_id) ;
+    }
+
+
+    /////////////////////////////
+    // Parent/Child Operations //
+    /////////////////////////////
+
+
+	public Cursor getChildren(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        return m_hierarchyIdx.getCursor(a_id) ;
+    }
+
+
+	public int getChildCount(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        return this.m_hierarchyIdx.count(a_id) ;
+    }
+
+
+	public Name getSuffix()
+    {
+        return m_suffix ;
+    }
+
+
+    public LdapEntryImpl getSuffixEntry()
+        throws BackendException, NamingException
+    {
+        return read(getEntryId(m_suffix.toString())) ;
+    }
+
+
+    public BigInteger getNextId()
+        throws BackendException
+    {
+        return m_master.getNextId() ;
+    }
+
+
+    public BigInteger getCurrentId()
+        throws BackendException
+    {
+        return m_master.getCurrentId() ;
+    }
+
+
+    public void sync()
+    {
+        Iterator l_list = m_indices.values().iterator() ;
+        while(l_list.hasNext()) {
+            Index l_index = (Index) l_list.next() ;
+
+            try {
+                l_index.sync() ;
+            } catch(Throwable t) {
+                super.getLogger().error("" //ProtocolModule.getMessageKey()
+                    + " - Database.sync(): Failed to sync index on attribute "
+                    + l_index.getAttribute()
+                    + " - index data may be lost.", t) ;
+            }
+        }
+
+        try {
+            this.m_existanceIdx.sync() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to sync the existance table data may be "
+                + "lost.", t) ;
+        }
+
+        try {
+            this.m_hierarchyIdx.sync() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to sync the hierarchy table data may be "
+                + "lost.", t) ;
+        }
+
+        try {
+            this.m_nameIdx.sync() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to sync the distinguished name table "
+                + "data may be lost.", t) ;
+        }
+
+        try {
+            m_master.sync() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to sync the master table data may be "
+                + "lost.", t) ;
+        }
+    }
+
+
+    public void close()
+    {
+        Iterator l_list = m_indices.values().iterator() ;
+        while(l_list.hasNext()) {
+            Index l_index = (Index) l_list.next() ;
+
+            try {
+               l_index.close() ;
+            } catch(Throwable t) {
+                getLogger().error("Failed to close index on attribute "
+                    + l_index.getAttribute()
+                    + " - index data may be lost.", t) ;
+            }
+        }
+
+        try {
+            this.m_existanceIdx.close() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to close the existance table data may be "
+                + "lost.", t) ;
+        }
+
+        try {
+            this.m_hierarchyIdx.close() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to close the hierarchy table data may be "
+                + "lost.", t) ;
+        }
+
+        try {
+            this.m_nameIdx.close() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to close the distinguished name table "
+                + "data may be lost.", t) ;
+        }
+
+        try {
+            m_master.close() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to close the master table data may be "
+                + "lost.", t) ;
+        }
+
+        try {
+            m_recMan.close() ;
+        } catch(Throwable t) {
+	        getLogger().error("Failed to close the database environment.", t) ;
+        }
+    }
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        super.enableLogging(a_logger) ;
+        log = a_logger ;
+	    m_nameIdx.enableLogging(a_logger) ;
+        m_existanceIdx.enableLogging(a_logger) ;
+        m_hierarchyIdx.enableLogging(a_logger) ;
+        m_master.enableLogging(a_logger) ;
+    }
+
+
+    /////////////////////
+    // Utility Methods //
+    /////////////////////
+
+
+    public void setProperty(String a_propertyName, String a_propertyValue)
+        throws BackendException
+    {
+        m_master.setProperty(a_propertyName, a_propertyValue) ;
+    }
+
+
+    public String getProperty(String a_propertyName)
+        throws BackendException
+    {
+        return this.m_master.getProperty(a_propertyName) ;
+    }
+
+
+    /**
+     * Lists only the User Defined Index (UDI) Attributes.
+     */
+    public Iterator getUDIAttributes()
+    {
+        return m_indices.keySet().iterator() ;
+    }
+
+
+    public final static String [] SYS_INDICES =
+    { Schema.DN_ATTR, Schema.EXISTANCE_ATTR, Schema.HIERARCHY_ATTR} ;
+
+    /**
+     * Gets the names of the maditory system indices used by the database.
+     * These names are used as the [operational] 'attribute' or key names
+     * of the indices.  All cursor operations and assertion operations use
+     * these names to select the appropriate UDI (User Defined Index) or SDI
+     * (System Defined Index) to operate upon.
+     */
+	public String [] getSystemIndices()
+    {
+		return SYS_INDICES ;
+    }
+
+
+    public MultiMap getIndices(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        MultiHashMap l_map = new MultiHashMap() ;
+
+        // Get the distinguishedName to id mapping
+        l_map.put("distinguishedName", m_nameIdx.getReverse(a_id)) ;
+
+        // Get all standard index attribute to value mappings
+        Iterator l_indices = m_indices.values().iterator() ;
+        while(l_indices.hasNext()) {
+            Index l_index = (Index) l_indices.next() ;
+            Cursor l_cursor = l_index.getReverseCursor(a_id) ;
+            while(l_cursor.hasMore()) {
+                IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+                Object l_val = l_rec.getIndexKey() ;
+                l_map.put(l_index.getAttribute(), l_val) ;
+            }
+        }
+
+        // Get all existance mappings for this id creating a special key
+        // that looks like so 'existance[attribute]' and the value is set to id
+        Cursor l_cursor = m_existanceIdx.getReverseCursor(a_id) ;
+        StringBuffer l_val = new StringBuffer() ;
+        while(l_cursor.hasMore()) {
+            IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+            l_val.append("existance[").append(l_rec.getIndexKey()).append(']') ;
+            l_map.put(l_val.toString(), l_rec.getEntryId()) ;
+            l_val.setLength(0) ;
+        }
+
+        // Get all parent child mappings for this entry as the parent using the
+        // key 'child' with many entries following it.
+        l_cursor = this.m_hierarchyIdx.getCursor(a_id) ;
+        while(l_cursor.hasMore()) {
+            IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+            l_map.put("child", l_rec.getEntryId()) ;
+        }
+
+        return l_map ;
+    }
+
+
+    private void addIndices(LdapEntry an_entry)
+        throws BackendException, NamingException
+    {
+        BigInteger l_id = ((LdapEntryImpl) an_entry).getEntryID() ;
+        Iterator l_list = an_entry.attributes().iterator() ;
+
+        m_nameIdx.add(an_entry.getNormalizedDN().toString(), l_id) ;
+
+        if(getLogger().isDebugEnabled() && debug) {
+			getLogger().debug("Adding name index ("
+                + an_entry.getNormalizedDN().toString()
+                + ", " + l_id.toString() + ")") ;
+        }
+
+        m_hierarchyIdx.add(((LdapEntryImpl) an_entry).getParentID(), l_id) ;
+
+        while(l_list.hasNext()) {
+            String l_attribute = (String) l_list.next() ;
+            String l_tolower = l_attribute.toLowerCase() ;
+
+            if(m_indices.containsKey(l_tolower)) {
+	            Index l_index = (Index) m_indices.get(l_tolower) ;
+	            Iterator l_values = // Get values using correct case.
+                    an_entry.getMultiValue(l_attribute).iterator() ;
+                while(l_values.hasNext()) {
+                    l_index.add((String) l_values.next(), l_id) ;
+                }
+
+                // Existance index will never be hit since 'existance' is not an
+	            // attribute based index in the formal sense. Nor are the name
+                // and hierarchy indices.
+	            m_existanceIdx.add(l_tolower, l_id) ;
+            }
+        }
+    }
+
+
+    private void dropIndices(LdapEntry an_entry)
+        throws BackendException, NamingException
+    {
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("JdbmModule.dropIndices(): deleting "
+                + "indices on entry\n" + an_entry) ;
+        }
+
+        BigInteger l_id = ((LdapEntryImpl) an_entry).getEntryID() ;
+        Iterator l_list = an_entry.attributes().iterator() ;
+
+        m_nameIdx.drop(an_entry.getNormalizedDN().toString(), l_id) ;
+        m_hierarchyIdx.drop(
+            ((LdapEntryImpl) an_entry).getParentID(), l_id) ;
+
+        while(l_list.hasNext()) {
+            String l_attribute = ((String) l_list.next()) ;
+            String l_tolower = l_attribute.toLowerCase() ;
+
+            if(m_indices.containsKey(l_tolower)) {
+	            Index l_index = (Index) m_indices.get(l_tolower) ;
+	            Iterator l_values = // Get values using correct case.
+                    an_entry.getMultiValue(l_attribute).iterator() ;
+                while(l_values.hasNext()) {
+                    l_index.drop((String) l_values.next(), l_id) ;
+                }
+
+                // Existance index will never be hit since 'existance' is not an
+	            // attribute based index in the formal sense. Nor are the name
+                // and hierarchy indices.
+	            m_existanceIdx.drop(l_tolower, l_id) ;
+            }
+        }
+    }
+
+
+    private void updateIndices( LdapEntryImpl an_entry )
+        throws BackendException, NamingException
+    {
+        if ( getLogger().isDebugEnabled() ) 
+        {
+            getLogger().debug( "" //ProtocolModule.getMessageKey()
+                + " - Database.updateIndices() - dumping delta hashes "
+                + "after removing the old dn and adding the new Dn" ) ;
+            getLogger().debug( "Added hash:\n" + an_entry.getAdded() ) ;
+            getLogger().debug( "Removed hash:\n" + an_entry.getRemoved() ) ;
+        }
+
+	    BigInteger l_id = an_entry.getEntryID() ;
+
+        //
+        // Remove indices for all attributes removed.
+        //
+
+        Iterator l_removedAttribs = an_entry.getRemoved().keySet().iterator() ;
+	    
+        while ( l_removedAttribs.hasNext() ) 
+        {
+	        String l_removedAttrib = ( String ) l_removedAttribs.next() ;
+	        String l_tolower = l_removedAttrib.toLowerCase() ;
+
+            if ( m_indices.containsKey( l_tolower ) ) 
+            {
+                Index l_index = ( Index ) m_indices.get( l_tolower ) ;
+
+                // Remove indices for all the removed values.
+	            Iterator l_values = ( ( Collection )
+	                an_entry.getRemoved().get( l_removedAttrib ) ).iterator() ;
+	            while ( l_values.hasNext() ) 
+                {
+                    Object l_val = l_values.next() ;
+                    if ( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "" //ProtocolModule.getMessageKey()
+                            + " - Database.updateIndices() - removing index "
+                            + l_tolower + " with value " + l_val ) ;
+                    }
+	                l_index.drop( l_val, l_id ) ;
+	            }
+
+                // Existance table must be handled specifically since it is not
+	            // an [operational] attribute and is not caught by the loop
+                // above. We need to make sure that we only remove an existance
+	            // index if all of the values for that attribute have been
+                // dropped.  We also need to watch out for stale keys to empty
+	            // collections in the multimap.
+	            if ( ! an_entry.containsKey( l_removedAttrib ) ) 
+                {
+	                m_existanceIdx.drop( l_tolower, l_id ) ;
+	            }
+	            else if ( an_entry.containsKey( l_removedAttrib ) &&
+	               an_entry.getMultiValue( l_removedAttrib ).size() == 0 )
+	            {
+	                m_existanceIdx.drop( l_tolower, l_id ) ;
+	            }
+            }
+            else if ( l_tolower.equals( "parentid" ) )
+            {
+                Iterator l_list = ( ( Collection ) 
+                    an_entry.getRemoved().get( l_removedAttrib) ).iterator() ;
+                    
+                while( l_list.hasNext() )
+                {
+                    BigInteger l_oldParentId = null ;
+                    Object l_obj = l_list.next() ;
+                    
+                    if ( l_obj instanceof String )
+                    {
+                        l_oldParentId = new BigInteger( ( String ) l_obj ) ; 
+                    }
+                    else if ( l_obj instanceof BigInteger )
+                    {
+                        l_oldParentId = ( BigInteger ) l_obj ;
+                    }
+                    
+                        
+                    m_hierarchyIdx.drop( l_oldParentId, l_id ) ;
+                    
+                    if( getLogger().isDebugEnabled() )
+                    {
+                        getLogger().debug( "removed old parentid '" 
+                            + l_oldParentId + "' from hierarchy index" ) ;
+                    }
+                }
+            } // Now we need to check for DN attribute changes due to modify ops
+            else if( l_tolower.equals( Schema.DN_ATTR ) ) 
+            {
+                Iterator l_list = ( ( Collection )
+                    an_entry.getRemoved().get( l_removedAttrib ) ).iterator() ;
+
+                while( l_list.hasNext() ) 
+                {
+                    Object l_oldDn = l_list.next() ;
+                    m_nameIdx.drop( l_oldDn, l_id ) ;
+
+                    if( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "removed old Dn '" + l_oldDn 
+                            + "' from name index" ) ;
+                    }
+                }
+            } // Close else if
+        } // Close while
+
+
+        //
+        // Create indices for all attribute value pairs added.
+        //
+
+        Iterator l_addedAttribs = an_entry.getAdded().keySet().iterator() ;
+	    while ( l_addedAttribs.hasNext() ) 
+        {
+	        String l_addedAttrib = ( String ) l_addedAttribs.next() ;
+            String l_tolower = l_addedAttrib.toLowerCase() ;
+
+            if ( m_indices.containsKey( l_tolower ) ) 
+            {
+                Index l_index = ( Index ) m_indices.get( l_tolower ) ;
+
+                // Create indices for all the added values.
+	            Iterator l_values = ( ( Collection )
+	                an_entry.getAdded().get( l_addedAttrib ) ).iterator() ;
+	            while ( l_values.hasNext() )  
+                {
+                    Object l_val = l_values.next() ;
+                    l_index.add( l_val, l_id ) ;
+                    
+                    if( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "" //ProtocolModule.getMessageKey()
+                            + " - Database.updateIndices() - added index "
+                            + l_tolower + " with value " + l_val ) ;
+                    }
+	            }
+
+                // Add an index into the existance table
+	            m_existanceIdx.add( l_tolower, l_id ) ;
+            } // Now we need to check for DN attribute changes due to modify ops
+            else if ( l_tolower.equals( "parentid" ) )
+            {
+                Iterator l_list = ( ( Collection )
+                    an_entry.getAdded().get( l_addedAttrib ) ).iterator() ;
+
+                while ( l_list.hasNext() ) 
+                {
+                    BigInteger l_newParentId = null ;
+                    Object l_obj = l_list.next() ;
+                    
+                    if ( l_obj instanceof String )
+                    {
+                        l_newParentId = new BigInteger( ( String ) l_obj ) ; 
+                    }
+                    else if ( l_obj instanceof BigInteger )
+                    {
+                        l_newParentId = ( BigInteger ) l_obj ;
+                    }
+                    
+                    m_hierarchyIdx.add( l_newParentId, l_id ) ;
+
+                    if ( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "added new Dn '" + l_newParentId 
+                            + "' to hierarchy index" ) ;
+                    }
+                }
+            }
+            else if ( l_tolower.equals( Schema.DN_ATTR ) ) 
+            {
+                Iterator l_list = ( ( Collection )
+                    an_entry.getAdded().get( l_addedAttrib ) ).iterator() ;
+
+                while ( l_list.hasNext() ) 
+                {
+                    String l_newDn = ( String ) l_list.next() ;
+                    m_nameIdx.add( l_newDn, l_id ) ;
+
+                    if ( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "added new Dn '"
+                            + l_newDn + "' to name index" ) ;
+                    }
+                }
+            } // Close else if
+        } // Close while
+    } // Close updateIndices()
+
+
+    /**
+     * Modifies the relative distinguished name (RDN) of an entry
+     * without changing any parent child relationships.  This call
+     * has the side effect of altering the distinguished name of
+     * descendent entries if they exist.  The boolean argument will
+     * optionally remove the existing RDN attribute value pair
+     * replacing it with the new RDN attribute value pair.  If other
+     * RDN attribute value pairs exist besides the current RDN they
+     * will be spared.
+     *
+     * @param an_entry the entry whose RDN is to be modified.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void modifyRdn( LdapEntryImpl an_entry,
+        String a_newRdn, boolean a_deleteOldRdn )
+	    throws BackendException, NamingException
+    {
+        String l_attribute = NamespaceTools.getRdnAttribute( a_newRdn ) ;
+	    String l_value = NamespaceTools.getRdnValue( a_newRdn ) ;
+
+        // This name is not Normalized since we want to preserve the user
+        // provided version of the Dn.
+	    Name l_name = m_nonNormalizingParser.parse( an_entry.getEntryDN() ) ;
+
+        if ( a_deleteOldRdn ||
+            m_schema.isSingleValue( l_attribute.toLowerCase() ) )
+        {
+	        String l_oldRdn = l_name.get( l_name.size() - 1 ) ;
+            String l_oldAttribute = NamespaceTools.getRdnAttribute( l_oldRdn ) ;
+            String l_oldValue = NamespaceTools.getRdnValue( l_oldRdn ) ;
+            
+	        an_entry.removeValue( l_oldAttribute, l_oldValue ) ;
+	    }
+
+        l_name.remove( l_name.size() - 1 ) ;
+	    l_name.add( l_name.size(), a_newRdn ) ;
+	    an_entry.addValue( l_attribute, l_value ) ;
+
+        if( getLogger().isDebugEnabled() ) 
+        {
+            getLogger().debug( "" //ProtocolModule.getMessageKey()
+                + " - Database.modifyRdn() - modifyDn() on entry '" 
+                + an_entry.getEntryDN() + "' using new Dn of '" 
+                + l_name + "'" ) ;
+        }
+
+	    modifyDn( ( LdapEntryImpl ) an_entry, l_name) ;
+    }
+
+
+    /**
+     * Recursively modifies the distinguished name of an entry and the names of
+     * its descendants calling itself in the recursion.
+     *
+     * @param an_entry Entry being altered to have a new DN.
+     * @param a_dn Distinguished name to set as the new DN
+     */
+    void modifyDn(LdapEntryImpl an_entry, Name a_dn)
+	    throws BackendException, NamingException
+    {
+        LdapEntryImpl l_child ;
+	    Cursor l_children ;
+	    Name l_childDN ;
+
+        if ( getLogger().isDebugEnabled() ) 
+        {
+            getLogger().debug( "" //ProtocolModule.getMessageKey()
+                + " - Database.modifyDn() - called on entry '"
+                + an_entry.getNormalizedDN() + "' to change it's DN to '"
+                + a_dn ) ;
+        }
+	
+        // Package friendly method that sets the user provided dn using
+	    // a name.  It automatically updates the normalized dn so it is
+	    // synchronized with the change.  setEntryDN must add the 
+	    // appropriate hints in the entry so the update can properly modify
+	    // indices.  If it seems like too much of a hassle then we can
+	    // handle index maintenance here with replication of update function
+	    // -ality.
+	    an_entry.setEntryDN( a_dn ) ;
+	    update( an_entry ) ;
+	    l_children = getChildren( an_entry.getEntryID() ) ;
+	
+        // List children using the DN since the updated parent has had
+	    // it's indices updated listChildren will lookup the id by dn
+	    // then use the parent child index to lookup all the children.
+	    while( l_children.hasMore() ) 
+        {
+            IndexRecord l_rec = ( IndexRecord ) l_children.next() ;
+	        l_child = read( l_rec.getEntryId() ) ;
+	        l_childDN = ( Name ) a_dn.clone() ;
+
+            // Add to the copy of the parent the unnormalized rdn of the child
+            // Dn to get the new Dn of the child entry - call recursively.
+	        l_childDN.add( 0,
+                NamespaceTools.getRdn( l_child.getEntryDN() ) ) ;
+            modifyDn( l_child, l_childDN ) ;
+	    }
+    }
+
+
+    /**
+     * This overload combines the first two method operations into one.
+     * It changes the Rdn and the parent prefix at the same time while
+     * recursing name changes to all descendants of the child entry. It
+     * is obviously more complex than the other two operations alone and
+     * involves changes to both parent child indices and DN indices.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move(LdapEntryImpl a_parentEntry, LdapEntryImpl a_childEntry,
+	    String a_newRdn, boolean a_deleteOldRdn)
+	    throws BackendException, NamingException
+    {
+        // @TODO NOT A VERY EFFICENT OPERATION AT ALL ! ! !  FIX IT ! ! !
+	    ( ( LdapEntryImpl ) a_childEntry ).setParent( ( LdapEntryImpl ) 
+            a_parentEntry ) ;
+        modifyRdn( a_childEntry, a_newRdn, a_deleteOldRdn ) ;
+        move( a_parentEntry, a_childEntry ) ;
+    }
+
+
+    /**
+     * Moves a child entry without changing the RDN under a new parent
+     * entry.  This effects the parent child relationship between the
+     * parent entry and the child entry.  The index for the child
+     * mapping it to the current parent is destroyed and a new index
+     * mapping it to the new parent is created.  As a side effect the
+     * name of the child entry and all its descendants will reflect the
+     * move within the DIT to a new parent.  The old parent prefix to
+     * the distinguished names of the child and its descendents will be
+     * replaced by the new parent DN prefix.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move( LdapEntryImpl a_parentEntry, LdapEntryImpl a_childEntry )
+	    throws BackendException, NamingException
+    {
+        Name l_parentDn =
+            m_nonNormalizingParser.parse( a_parentEntry.getEntryDN() ) ;
+	    Name l_childDn =
+            m_nonNormalizingParser.parse( a_childEntry.getEntryDN() ) ;
+	    String l_rdn = l_childDn.get( l_childDn.size() - 1 ) ;
+	
+        // This call should be package friendly and should automatically
+	    // replace the current parent id and dn operational attributes 
+	    // with the new parent's respective operational attribute values.
+	    ( ( LdapEntryImpl ) a_childEntry ).setParent( 
+            ( LdapEntryImpl ) a_parentEntry ) ;
+            
+	    Name l_newDn = l_parentDn ;
+	    l_newDn.add( l_newDn.size(), l_rdn ) ;
+	    modifyDn( ( LdapEntryImpl ) a_childEntry, l_newDn ) ;
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/JdbmModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,596 @@
+/*
+ * $Id: JdbmModule.java,v 1.11 2003/08/06 03:01:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import java.math.BigInteger ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.NameNotFoundException ;
+import javax.naming.ContextNotEmptyException ;
+import javax.naming.NameAlreadyBoundException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.schema.SchemaManager ;
+import org.apache.eve.backend.BackendModule ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.search.SearchEngine ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+import org.apache.commons.collections.LRUMap ;
+import org.apache.eve.backend.jdbm.gui.BackendFrame ;
+
+
+/**
+ * Jdbm backend module.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.backend.AtomicBackend"
+ * @phoenix:mx-topic name="jdbm-backend"
+ */
+public class JdbmModule
+    extends BackendModule
+{
+    private JdbmDatabase m_db = null ;
+    private SearchEngine m_searchEngine = null ;
+
+    private Object m_cacheLock = new Object() ;
+    private LRUMap m_byIdCache = new LRUMap() ;
+
+
+    public JdbmDatabase getDatabase()
+    {
+        return m_db ;
+    }
+
+
+    private void addToCache(org.apache.eve.backend.jdbm.LdapEntryImpl an_entry)
+        throws NamingException
+    {
+        synchronized(m_cacheLock) {
+            super.m_cache.put(an_entry.getNormalizedDN().toString(), an_entry) ;
+            this.m_byIdCache.put(an_entry.getEntryID(), an_entry) ;
+        }
+    }
+
+
+    private void removeFromCache(org.apache.eve.backend.jdbm.LdapEntryImpl an_entry)
+        throws NamingException
+    {
+        synchronized(m_cacheLock) {
+            super.m_cache.remove(an_entry.getNormalizedDN().toString()) ;
+            this.m_byIdCache.remove(an_entry.getEntryID()) ;
+        }
+    }
+
+
+    //////////////////////////////////
+    // Backend Crud Implementations //
+    //////////////////////////////////
+
+
+    public void delete( LdapEntry an_entry )
+        throws BackendException, NamingException
+    {
+        LdapEntryImpl l_entry = ( LdapEntryImpl ) an_entry ;
+
+        if( ! l_entry.isValid() )
+        {
+            throw new BackendException( "Cannot perform delete operation on "
+                + "invalid entry: " + l_entry ) ;
+        }
+
+        if( m_db.getChildCount( l_entry.getEntryID() ) > 0 )
+        {
+            // Exception translates to NOTALLOWEDONLEAF LDAPv3 result code (66)
+            ContextNotEmptyException e = new ContextNotEmptyException(
+                "[66] Cannot delete entry " + l_entry.getEntryDN()
+                + " it has children!" ) ;
+            e.setRemainingName( l_entry.getNormalizedDN() ) ;
+            throw e ;
+        }
+
+        BigInteger l_id = l_entry.getEntryID() ;
+        m_db.delete( l_id ) ;
+        removeFromCache( ( LdapEntryImpl ) an_entry ) ;
+    }
+
+
+    /**
+     * Creates a new invalid entry ready to be populated and created within this
+     * backend module.
+     *
+     * @param a_dn the non-normalized user provided distinguished name of the
+     * new entry to create.
+     * @throws NameAlreadyBoundException if an entry with a_dn already exists
+     * within this backend.
+     * @throws javax.naming.InvalidNameException if a_dn does not conform to the dn syntax
+     * @throws NameNotFoundException if a_dn is not suffix and does not have a
+     * parent to be attached to.
+     */
+    public LdapEntry newEntry( String a_dn )
+        throws BackendException, NamingException
+    {
+        // Will throw InvalidNameException if a_dn is syntactically incorrect.
+        Name l_dn = m_schema.getNormalizingParser().parse( a_dn ) ;
+        if( m_db.getEntryId( l_dn.toString() ) != null )
+        {
+            // NameAlreadyBoundExceptions correspond to a NAMEALREADYEXISTS
+            // result code with a value of [68] within the LDAPv3 protocol.
+	        NameAlreadyBoundException e = new NameAlreadyBoundException(
+                "[68] '" + a_dn + "' is already bound." ) ;
+            e.setResolvedName( l_dn ) ;
+            throw e ;
+        }
+
+        //
+        // We only check for the existance of a parent entry if the new entry
+        // to add is not a suffix.  This is because a suffix entry will not
+        // have a parent node.
+        //
+
+        if( ! l_dn.equals( getSuffix() ) )
+        {
+            Name l_parent = l_dn.getSuffix( 1 ) ;
+            if( m_db.getEntryId( l_parent.toString() ) == null )
+            {
+                // NameNotFoundExceptions in JNDI correspond to the NOSUCHOBJECT
+                // result code of the LdapResult of the response in LDAPv3
+                NameNotFoundException e = new NameNotFoundException(
+                    "[32] Parent entry '" + l_parent
+					+ "' does not exist.  Cannot create " + l_dn.get(0)
+                    + " without parent." ) ;
+                throw e ;
+            }
+        }
+
+        LdapEntryImpl l_entry = new LdapEntryImpl( m_schema, l_dn, a_dn ) ;
+        l_entry.enableLogging( getLogger() ) ;
+        return l_entry ;
+    }
+
+
+    public LdapEntry read( Name a_dn )
+        throws BackendException, NamingException
+    {
+        if( m_cache.containsKey( a_dn.toString() ) )
+        {
+            return ( LdapEntry ) m_cache.get( a_dn.toString() ) ;
+        }
+
+        BigInteger l_id = m_db.getEntryId( a_dn.toString() ) ;
+
+        if( l_id == null )
+        {
+	        throw new NameNotFoundException( "[32] '" + a_dn
+                + "' does not exist!" ) ;
+        }
+
+        LdapEntryImpl l_entry = m_db.read( l_id ) ;
+        l_entry.enableLogging( getLogger() ) ;
+        addToCache( l_entry ) ;
+        return l_entry ;
+    }
+
+
+    LdapEntry read(BigInteger l_id)
+        throws BackendException, NamingException
+    {
+        if(this.m_byIdCache.containsKey(l_id)) {
+            return (LdapEntry) m_byIdCache.get(l_id) ;
+        }
+
+        LdapEntryImpl l_entry = m_db.read(l_id) ;
+        l_entry.enableLogging(getLogger()) ;
+        addToCache(l_entry) ;
+        return l_entry ;
+    }
+
+
+    /**
+     * Updates an entry in the backing store.
+     *
+     * @param an_entry the modified entry to update.
+     */
+    public void update(LdapEntry an_entry)
+        throws BackendException, NamingException
+    {
+        removeFromCache((LdapEntryImpl) an_entry) ;
+	    m_db.update((LdapEntryImpl) an_entry) ;
+        addToCache((LdapEntryImpl) an_entry) ;
+    }
+
+
+    public void create(LdapEntry an_entry)
+        throws BackendException, NamingException
+    {
+        LdapEntryImpl l_entry = (LdapEntryImpl) an_entry ;
+
+        if(l_entry.isValid()) {
+            throw new BackendException("Cannot create entries that have "
+                + "already been created!") ;
+        }
+
+        // Add operational attributes!
+        BigInteger l_id = m_db.getNextId() ;
+        LdapEntryImpl l_parent = null ;
+        BigInteger l_parentId = null ;
+        l_entry.put(LdapEntry.ID_ATTR, l_id.toString()) ;
+
+        if(l_entry.getNormalizedDN().equals(m_suffix)) {
+            l_entry.put(LdapEntry.PARENTID_ATTR, l_id.toString()) ;
+            l_entry.put(LdapEntry.PARENTDN_ATTR, l_entry.getEntryDN()) ;
+            l_parent = l_entry ;
+            l_parentId = l_id ;
+        } else {
+            l_parent = (LdapEntryImpl) getParent(l_entry.getNormalizedDN()) ;
+            l_parentId = l_parent.getEntryID() ;
+            l_entry.put(LdapEntry.PARENTID_ATTR, l_parentId.toString()) ;
+            l_entry.put(LdapEntry.PARENTDN_ATTR, l_parent.getEntryDN()) ;
+        }
+
+        m_db.create(l_entry, l_id) ;
+        addToCache(l_entry) ;
+    }
+
+
+    ///////////////////////////////////////
+    // Search and Modify Implementations //
+    ///////////////////////////////////////
+
+
+    /**
+     * Searches for candidate entries on the backend starting on a base DN 
+     * using a search filter with search controls.
+     * 
+     * The distinguished name argument is NOT presumed to be normalized in
+     * accordance with schema attribute syntax and attribute matching rules.
+     * The DN is also NOT presumed to be syntacticly correct or within the
+     * namespace of this directory information base.  Unaware of normalization
+     * this method will attempt to normalize any DN arguements.  Apriori
+     * normalization would be redundant.
+     *
+     * W O R K   I N   P R O G R E S S
+     *
+     * @param a_filter String representation of an LDAP search filter.
+     * @param a_baseDn String representing the base of the search.
+     * @param a_scope SearchControls governing how this search is to be
+     * conducted.
+     * @throws BackendException on Backend errors or when the operation cannot
+     * proceed due to a malformed search filter, a non-existant search base, or
+     * inconsistant search controls.
+     * @throws javax.naming.InvalidNameException if a_baseDN is not syntactically correct.
+     * @throws NameNotFoundException when a component of a_baseDN cannot be
+     * resolved because it is not bound.
+     * @throws javax.naming.directory.InvalidSearchFilterException when the specification of a search
+     * filter is invalid. The expression of the filter may be invalid, or there
+     * may be a problem with one of the parameters passed to the filter.
+     * @throws javax.naming.directory.InvalidSearchControlsException when the specification of the
+     * SearchControls for a search operation is invalid. For example, if the
+     * scope is set to a value other than OBJECT_SCOPE, ONELEVEL_SCOPE,
+     * SUBTREE_SCOPE, this exception is thrown.
+     */
+    public Cursor search(ExprNode a_filter, Name a_baseDn, int a_scope)
+        throws BackendException, NamingException
+    {
+        Cursor l_cursor = new EntryCursor(this,
+            m_searchEngine.search(m_db, a_filter,
+            a_baseDn.toString(), a_scope)) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    /**
+     * Modifies the relative distinguished name (RDN) of an entry
+	 * without changing any parent child relationships.  This call
+	 * has the side effect of altering the distinguished name of
+	 * descendent entries if they exist.  The boolean argument will
+	 * optionally remove the existing RDN attribute value pair
+	 * replacing it with the new RDN attribute value pair.  If other
+	 * RDN attribute value pairs exist besides the current RDN they
+	 * will be spared.
+     *
+     * @param an_entry the entry whose RDN is to be modified.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void modifyRdn( LdapEntry an_entry, Name a_newRdn,
+        boolean a_deleteOldRdn )
+	    throws BackendException, NamingException
+    {
+        m_db.modifyRdn( ( LdapEntryImpl ) an_entry,
+            a_newRdn.toString(), a_deleteOldRdn ) ;
+    }
+
+
+    /**
+     * Moves a child entry without changing the RDN under a new parent
+     * entry.  This effects the parent child relationship between the
+     * parent entry and the child entry.  The index for the child
+     * mapping it to the current parent is destroyed and a new index
+     * mapping it to the new parent is created.  As a side effect the
+     * name of the child entry and all its descendants will reflect the
+     * move within the DIT to a new parent.  The old parent prefix to
+     * the distinguished names of the child and its descendents will be
+     * replaced by the new parent DN prefix.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move( LdapEntry a_parentEntry, LdapEntry a_childEntry )
+	    throws BackendException, NamingException
+    {
+        m_db.move( ( LdapEntryImpl ) a_parentEntry, 
+            ( LdapEntryImpl ) a_childEntry) ;
+    }
+
+
+    /**
+     * This overload combines the first two method operations into one.
+     * It changes the Rdn and the parent prefix at the same time while
+	 * recursing name changes to all descendants of the child entry. It
+	 * is obviously more complex than the other two operations alone and
+	 * involves changes to both parent child indices and DN indices.
+     *
+     * @param a_parentEntry the parent the child is to subordinate to.
+     * @param a_childEntry the child to be moved under the parent.
+     * @param a_newRdn the new Rdn that is to replace the current Rdn.
+     * @param a_deleteOldRdn deletes the old Rdn attribute value pair if true.
+     * @throws BackendException when the operation cannot be performed due to a
+     * backing store error.
+     * @throws NamingException when naming violations and or schema violations
+     * occur due to attempting this operation.
+     */
+    public void move( LdapEntry a_parentEntry, LdapEntry a_childEntry,
+	    Name a_newRdn, boolean a_deleteOldRdn )
+	    throws BackendException, NamingException
+    {
+        m_db.move( ( LdapEntryImpl ) a_parentEntry, 
+            ( LdapEntryImpl ) a_childEntry,
+            a_newRdn.toString(), a_deleteOldRdn ) ;
+    }
+
+
+    ///////////////////////////////////////
+    // Remaining Backend Implementations //
+	///////////////////////////////////////
+
+
+    public LdapEntry getParent(Name a_childDN)
+        throws BackendException, NamingException
+    {
+	    return read(a_childDN.getSuffix(1)) ;
+    }
+
+
+    public boolean hasEntry(Name a_dn)
+        throws BackendException, NamingException
+    {
+        return m_db.getEntryId(a_dn.toString())
+            != null ;
+    }
+
+
+    public boolean isSuffix(LdapEntry an_entry)
+        throws NamingException 
+    {
+        return an_entry.getNormalizedDN().equals(m_suffix) ;
+    }
+
+
+    public boolean isAdminUser(Name a_userDn)
+        throws NamingException
+    {
+	    if(a_userDn.equals(m_adminUser)) {
+            return true ;
+        }
+
+        return false ;
+    }
+
+
+    public Cursor listChildren(Name a_parentDN)
+        throws BackendException, NamingException
+    {
+        BigInteger l_id =
+            m_db.getEntryId(a_parentDN.toString()) ;
+
+        if(l_id == null) {
+            throw new NameNotFoundException("Cannot list the children of "
+                + a_parentDN + ".  It does not exist!") ;
+        }
+
+        Cursor l_cursor = new EntryCursor(this, m_db.getChildren(l_id)) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public String getProperty(String a_propertyName)
+        throws BackendException
+    {
+	    return m_db.getProperty(a_propertyName) ;
+    }
+
+
+    public void setProperty(String a_propertyName, String a_propertyValue)
+        throws BackendException
+    {
+        m_db.setProperty(a_propertyName, a_propertyValue) ;
+    }
+
+
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return("Jdbm DB Implementation") ;
+    }
+
+
+    /**
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation class name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    /**
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the suffix of this backend.
+     * @phoenix:mx-isWriteable no
+     */
+    public Name getSuffix()
+    {
+        return m_db.getSuffix() ;
+    }
+
+
+    /**
+     * @phoenix:mx-operation
+     * @phoenix:mx-description Synchronizes cached berkeley data with disk.
+     */
+    public void sync()
+        throws BackendException
+    {
+        m_db.sync() ;
+    }
+
+
+    /**
+     * @phoenix:mx-operation
+     * @phoenix:mx-description Invokes the admin tool gui.
+     */
+    public void invokeAdminTool()
+        throws Exception
+    {
+        try {
+			BackendFrame l_frame = new BackendFrame() ;
+            l_frame.enableLogging(getLogger()) ;
+			l_frame.loadDatabase(m_db) ;
+            l_frame.launch() ;
+        } catch(Exception e) {
+            getLogger().error("Got the following exception while trying to "
+                + "invoke the admin tool: " + e.getMessage() + "\n\nTrace:\n"
+                + ExceptionUtil.printStackTrace(e)) ;
+        }
+    }
+
+
+    /////////////////////////////////////////////
+    // Configuration Interface Implementations //
+    /////////////////////////////////////////////
+
+    public static final String INDICES_TAG = "indices" ;
+    public static final String INDEX_TAG = "index" ;
+	public static final String INAME_ATTR = "name" ;
+
+    /**
+     * Avalon Configurable interface implementation specific to a Berkeley Db.
+     * Here's an example configuration with a "cn" and ""dc" index. Notice
+     * that the standard backend configuration attributes are not included:<br>
+     * 
+     *   <config>
+     *		<backend>
+     * 			<indices>
+     * 			<index name="cn"/>
+     * 			<index name="dc"/>
+     * 			</indices>
+     *		</backend>
+     *   </config>
+     *
+     * @param a_config an avalon configuration object for this backend block.
+     * @throws ConfigurationException if the configuration is not correct.
+     */
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+        super.configure(a_config) ;
+
+        ///////////////////////////////////////////////
+        // Configure Backend Database and Components //
+        ///////////////////////////////////////////////
+
+        try {
+            m_byIdCache.setMaximumSize(m_cache.getMaximumSize()) ;
+            m_searchEngine = new SearchEngine() ;
+            m_searchEngine.enableLogging(getLogger()) ;
+            m_db = new JdbmDatabase (m_schema, m_suffix, m_wkdirPath) ;
+	        m_db.enableLogging(getLogger()) ;
+
+            Configuration [] l_indices =
+	            a_config.getChild(INDICES_TAG).getChildren(INDEX_TAG) ;
+	        String l_attribName = null ;
+	        for(int ii = 0; ii < l_indices.length; ii++) {
+	            l_attribName = l_indices[ii].getAttribute(INAME_ATTR) ;
+                m_db.addIndexOn(l_attribName) ;
+	        }
+        } catch(NamingException e) {
+            throw new ConfigurationException("Could not configure "
+                + getImplementationName() + " with suffix " + m_suffix
+                + " due to NamingException:\n" + e.getMessage(), e) ;
+        } catch(BackendException e) {
+            throw new ConfigurationException("Could not configure "
+                + getImplementationName() + " with suffix " + m_suffix
+                + " due to NamingException:\n" + e.getMessage(), e) ;
+        }
+    }
+
+
+    public void stop()
+        throws Exception
+    {
+        super.stop() ;
+        m_db.close() ;
+    }
+
+
+    /**
+     * @phoenix:dependency name="org.apache.eve.schema.SchemaManager"
+     * @phoenix:dependency name="org.apache.eve.backend.UnifiedBackend"
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        super.service(a_manager) ;
+        m_schemaManager =
+            (SchemaManager) a_manager.lookup(SchemaManager.ROLE) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/LdapEntryImpl.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/LdapEntryImpl.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,850 @@
+/*
+ * $Id: LdapEntryImpl.java,v 1.9 2003/08/06 03:01:25 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm ;
+
+
+import java.util.Date ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Collection ;
+import java.math.BigInteger ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.directory.AttributeInUseException ;
+import javax.naming.directory.InvalidAttributeValueException ;
+import javax.naming.directory.AttributeModificationException ;
+import javax.naming.directory.InvalidAttributeIdentifierException ;
+
+import org.apache.ldap.common.util.NamespaceTools ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.protocol.ProtocolModule;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.logger.LogEnabled ;
+
+import org.apache.commons.collections.LRUMap ;
+import org.apache.commons.collections.MultiHashMap ;
+import org.apache.ldap.common.name.DnParser;
+
+
+/**
+ * An entry implementation for the Berkeley backend.
+ * 
+ * @task No schema checking going on right now - but this needs to change!
+ * @task Also we need to make sure that we are storing dates in the apropriate
+ * fashion
+ */
+public class LdapEntryImpl
+    extends MultiHashMap
+	implements LdapEntry, LogEnabled
+{
+    private final Schema m_schema ;
+    private Logger m_log ;
+    private Name m_normalizedDn ;
+    private Name m_dn ;
+    private boolean m_isValid = false ;
+    private BigInteger m_id ;
+    private HashMap m_attrIdMap = new HashMap() ;
+    private LRUMap m_attrIdCache = new LRUMap(25) ;
+
+    // Only used on validated entries - validation initializes them.
+    private MultiHashMap m_added = null ;
+    private MultiHashMap m_removed = null ;
+
+
+	LdapEntryImpl( Schema a_schema, Name a_dName, String a_dnStr )
+    {
+        m_schema = a_schema ;	       				// schema this entry uses
+        m_normalizedDn = a_dName ;	    			// normalized parsed name
+        put( DN_ATTR, a_dnStr ) ;	    			// user provided name
+    }
+
+
+    LdapEntryImpl(Schema a_schema)
+    {
+        m_schema = a_schema ;
+    }
+
+
+    /**
+     * Note that according to the Backend-Server contract this method must
+     * return a Collection of attribute identifier names as they were
+     * specified by the user at creation time.  These are not normalized
+     * attribute identifiers.
+     */
+    public Collection attributes()
+    {
+        return this.keySet() ;
+    }
+
+
+    public Schema getSchema()
+    {
+        return m_schema ;
+    }
+
+
+	public boolean equals(String a_dn)
+        throws NamingException
+    {
+        String l_normalized = m_schema.normalize(Schema.DN_ATTR, a_dn) ;
+        Name l_name = this.getNormalizedDN() ;
+        return l_name.toString().equals(l_normalized) ;
+    }
+
+
+    public boolean hasAttribute(String an_attributeName)
+    {
+        return containsKey(an_attributeName) ;
+    }
+
+
+    public boolean hasAttributeValuePair(String an_attribute, Object a_value)
+    {
+        if(containsKey(an_attribute)) {
+            Collection l_collection = getMultiValue(an_attribute) ;
+
+            if(null == l_collection && null == a_value) {
+                return true ;
+            } else if(null == l_collection || null == a_value) {
+                return false ;
+            } else if(l_collection.contains(a_value)) {
+                return true ;
+            } else {
+                return false ;
+            }
+        } else {
+	    return false ;
+        }
+    }
+
+
+    /**
+     * Gets this entry's creation timestamp as a Date.
+     *
+     * @return Date representing the creation timestamp of this entry.
+     */
+    public Date getCreateTimestamp()
+    {
+	return new Date((String) getSingleValue(CREATETIMESTAMP_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the creator of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the distinguished name of the creator.
+     */
+    public String getCreatorsName()
+    {
+        return (String) getSingleValue(CREATORSNAME_ATTR) ;
+    }
+
+
+    /**
+     * Gets the unique distinguished name associated with this entry as it was
+     * supplied during creation without whitespace trimming or character case
+     * conversions.  This version of the DN is kept within the body of this
+     * Entry as an operational attribute so that it could be returned as it was
+     * given to the server w/o normalization effects: case and whitespace will
+     * be entact.
+     *
+     * @return the distinguished name of this entry as a String.
+     */
+    public String getEntryDN()
+    {
+        return (String) getSingleValue(DN_ATTR) ;
+    }
+
+
+    /**
+     * Gets the unique identifier of this entry as a BigInteger.
+     *
+     * @return BigInteger unique identifier of this entry.
+     */
+    public BigInteger getEntryID()
+    {
+        if(m_id == null) {
+            m_id = new BigInteger((String) getSingleValue(ID_ATTR)) ;
+        }
+
+        return m_id ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the last modifier of this entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return the DN of the user to modify this entry last.
+     */
+    public String getModifiersName()
+    {
+        return (String) getSingleValue(MODIFIERSNAME_ATTR) ;
+    }
+
+
+    /**
+     * Gets this entry's modification timestamp as a Date.
+     *
+     * @return Date representing the timestamp this entry was last modified.
+     */
+    public Date getModifyTimestamp()
+    {
+        return new Date((String)
+            getSingleValue(MODIFYTIMESTAMP_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the normalized unique distinguished name associated with this 
+     * entry. This DN unlike the user specified DN accessed via getDN() is not
+     * an operational attribute composing the body of this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this entry as a String.
+     */
+    public Name getNormalizedDN()
+        throws NamingException
+    {
+        if(m_normalizedDn == null) {
+            m_normalizedDn =
+                m_schema.getNormalizingParser().parse(getEntryDN()) ;
+        }
+
+        return m_normalizedDn;
+    }
+
+
+    /**
+     * Gets a Name representation of the originally user provided name without
+     * any case conversions.  I added this method so we can cache this value
+     * and avoid the reparse via the use of the nexus getName method.
+     */
+    public Name getUnNormalizedDN()
+        throws NamingException
+    {
+        if(m_dn == null) {
+            m_dn = m_schema.getNameParser().parse(getEntryDN()) ;
+        }
+
+        return m_dn ;
+    }
+
+
+    /**
+     * Gets the number of subordinate child entries that exist for this Entry.
+     *
+     * @return the number of subordinates (children).
+     */
+    public BigInteger getNumSubordinates()
+    {
+        return new BigInteger((String)
+            getSingleValue(NUMSUBORDINATES_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the normalized unique distinguished name of this Entry's parent.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     *
+     * @return the normalized distinguished name of this Entry's parent.
+     */
+    public String getParentDN()
+    {
+        return (String) getSingleValue(PARENTDN_ATTR) ;
+    }
+
+
+    /**
+     * Gets the unique identifier of this entry's parent entry as a BigInteger.
+     * The parent ID is equal to the entry id <code>
+     * (getEntryID().equals(parentID()) == true) </code> if this entry is a 
+     * root (a.k.a. suffix) entry.
+     *
+     * @return the uid of this entry's parent.
+     */
+    public BigInteger getParentID()
+    {
+        return new BigInteger((String) getSingleValue(PARENTID_ATTR)) ;
+    }
+
+
+    /**
+     * Gets the distinguished name of the subschema subentry for this Entry.
+     *
+     * The distinguished name is presumed to be normalized by the server naming
+     * subsystem in accordance with schema attribute syntax and attribute
+     * matching rules. The DN is also presumed to be syntacticly correct and
+     * within the namespace of this directory information base from which this
+     * Entry originated.
+     * 
+     * @return String of the subschema subentry distinguished name.
+     */
+    public String getSubschemaSubentryDN()
+    {
+        return (String) getSingleValue(SUBSCHEMASUBENTRY_ATTR) ;
+    }
+
+
+    /**
+     * Checks whether or not this Entry is a valid entry residing within a
+     * backend.  Entries are validated on successful create() calls.  When
+     * Entry instances are initialized in the java sense via the newEntry()
+     * call on backends, they are in the invalid state.
+     *
+     * @return true if this entry has been persisted to a backend,
+     * false otherwise.
+     */
+    public boolean isValid()
+    {
+        return m_isValid ;
+    }
+
+
+    /**
+     * Gets a multivalued attribute by name.
+     *
+     * @param a_attribName the name of the attribute to lookup.
+     * @return a Collection or null if no attribute value exists.
+     */
+    public Collection getMultiValue(String an_attribName)
+    {
+        return (Collection) get(an_attribName) ;
+    }
+
+
+    /**
+     * Gets a single valued attribute by name or returns the first value of a
+     * multivalued attribute.
+     *
+     * @param a_attribName the name of the attribute to lookup.
+     * @return an Object value which is either a String or byte [] or null if
+     * the attribute does not exist.
+     */
+    public Object getSingleValue(String an_attribName)
+    {
+        Collection l_col = (Collection) get(an_attribName) ;
+
+		if(null == l_col || l_col.isEmpty()) {
+            return null ;
+        }
+
+        return l_col.iterator().next() ;
+    }
+
+
+    private void checkIdentifier( String an_attribName )
+        throws InvalidAttributeIdentifierException
+    {
+		if( ! m_schema.hasAttribute( an_attribName ) )
+        {
+            // InvalidAttributeIdentifierException JNDI exceptions corresponds
+            // to an UNDEFINEDATTRIBUTETYPE result code within LDAPv2 with a
+            // value of [17]
+            throw new InvalidAttributeIdentifierException(
+                "[17] " + an_attribName +
+                " is not a valid schema recognized attribute name." ) ;
+        }
+    }
+
+
+    /**
+     * Adds a value to this Entry potentially resulting in more than one value
+     * for the attribute/key.
+     * 
+     * @param an_attribName attribute name/key
+     * @param a_value the value to add
+     * @throws InvalidAttributeIdentifierException when an attempt is made to
+     * add to or create an attribute with an invalid attribute identifier.
+     * @throws InvalidAttributeValueException when an attempt is made to add to
+     * an attribute a value that conflicts with the attribute's schema
+     * definition. This could happen, for example, if attempting to add an
+     * attribute with no value when the attribute is required to have at least
+     * one value, or if attempting to add more than one value to a single
+     * valued-attribute, or if attempting to add a value that conflicts with 
+     * the syntax of the attribute.
+     */
+    public void addValue(String an_attribName, Object a_value)
+        throws
+        AttributeInUseException,
+        InvalidAttributeValueException,
+        InvalidAttributeIdentifierException
+    {
+        // Null args have no affect
+	    if( null == a_value || null == an_attribName )
+        {
+            return ;
+        }
+
+		checkIdentifier( an_attribName ) ;
+
+		if( containsKey( an_attribName ) &&
+            m_schema.isSingleValue( an_attribName ) )
+        {
+            // AttributeInUseException JNDI exceptions correspond to
+            // ATTRIBUTEORVALUEEXISTS result code in LDAPv3 with a value of [20]
+            throw new AttributeInUseException( "[20] A key for attribute "
+                + an_attribName + " already exists!" ) ;
+        }
+
+
+        // Indices do not exist on binary attributes so there is no need to
+        // update them or for that matter track changes to them
+        if( m_schema.isBinary( an_attribName ) )
+        {
+            put( an_attribName, a_value ) ;
+        }
+
+        // @todo Answer why we are not asking the schema here if the value is
+        // valid when we are dealing with numbers? Shouldn't we be performing
+        // some form of syntax check?
+        else if( m_schema.isNumeric( an_attribName ) ||
+            m_schema.isDecimal( an_attribName ) )
+        {
+            put( an_attribName, a_value ) ;
+
+            if( m_isValid )
+            {
+                m_added.put( an_attribName, a_value ) ;
+            }
+        }
+        else
+        {
+            String l_value = ( String ) a_value ;
+
+    	    if( l_value.trim().equals( "" ) )
+    		{
+                return ;
+            }
+
+            if( ! m_schema.isValidSyntax( an_attribName, l_value ) )
+            {
+                // InvalidAttributeValueException JNDI exceptions correspond to
+                // the INVALIDATTRIBUTESYNTAX result code with a value of [21]
+                throw new InvalidAttributeValueException( "[21] '" + l_value
+                    + "' does not comply with the syntax for attribute "
+                    + an_attribName ) ;
+            }
+
+            put( an_attribName, l_value ) ;
+
+            if( m_isValid )
+            {
+                m_added.put( an_attribName, l_value ) ;
+            }
+        }
+    }
+
+
+    /**
+     * Removes the attribute/value pair in this Entry only without affecting
+     * other values that the attribute may have.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_value the value to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValue( String an_attribName, Object a_value )
+        throws InvalidAttributeIdentifierException
+    {
+		checkIdentifier( an_attribName ) ;
+
+        if( m_schema.isBinary( an_attribName ) )
+        {
+            remove( an_attribName, a_value ) ;
+        }
+        else
+        {
+            remove( an_attribName, a_value ) ;
+
+        	// For valid entries within the backend we track what we added and
+            // removed.  Need to remove values added to shadow copy that now get
+            // removed.
+            if( m_isValid )
+            {
+                m_removed.put( an_attribName, a_value ) ;
+                m_added.remove( an_attribName, a_value ) ;
+            }
+        }
+    }
+
+
+    /**
+     * Removes all the attribute/value pairs in this Entry associated with the
+     * attribute.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_value the value to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValues( String an_attribName )
+        throws InvalidAttributeIdentifierException
+    {
+		checkIdentifier( an_attribName ) ;
+
+        // Don't care if the value does not exist
+        if( ! containsKey( an_attribName ) )
+        {
+            return ;
+        }
+
+        Iterator l_removed = getMultiValue( an_attribName ).iterator() ;
+        if( m_isValid )
+        {
+			while( l_removed.hasNext() )
+            {
+					m_removed.put( an_attribName, l_removed.next() ) ;
+			}
+	
+			m_added.remove( an_attribName ) ;
+		}
+
+		remove( an_attribName ) ;
+    }
+
+
+    /**
+     * Removes the specified set of attribute/value pairs in this Entry.
+     *
+     * @param an_attribName attribute name/key
+     * @param a_valueArray the set of values to remove
+     * @throws AttributeModificationException when an attempt is made to modify
+     * an attribute, its identifier, or its values that conflicts with the
+     * attribute's (schema) definition or the attribute's state.  Also thrown
+     * if the specified attribute name does not exist as a key in this Entry.
+     */
+    public void removeValues(String an_attribName, Object [] a_valueArray)
+        throws InvalidAttributeIdentifierException
+    {
+		checkIdentifier( an_attribName ) ;
+
+        for( int ii = 0; ii < a_valueArray.length; ii++ )
+        {
+            remove( an_attribName, a_valueArray[ii] ) ;
+        }
+    }
+
+
+    //////////////////////////////
+    // Package Friendly Methods //
+    //////////////////////////////
+
+
+    /**
+     * This method is called to indicate that this entry has now been created
+     * within a backend.  Any alterations to be made to is are going to be
+     * tracked using the three multimaps.  The add, remove and change methods
+     * will on use now begin to add attribute into the appropriate multimap
+     * resouvoirs to enable store optimization on updates.
+     */
+    void validate()
+    {
+        m_isValid = true ;
+
+		if(null == m_added) {
+	    	m_added = new MultiHashMap() ;
+        } else {
+            m_added.clear() ;
+        }
+
+        if(null == m_removed) {
+	    	m_removed = new MultiHashMap() ;
+        } else {
+            m_removed.clear() ;
+        }
+    }
+
+
+    MultiHashMap getRemoved()
+    {
+        return m_removed ;
+    }
+
+    
+    MultiHashMap getAdded()
+    {
+        return m_added ;
+    }
+
+
+    /**
+     * Sets the parent id and parent dn operational attributes of this 
+     * entry to correspond to a new parent entry.  The appropriate changes
+     * are made to the added and removed multimaps to correctly update
+     * this entry with the new parent child relationship.  Effects are not
+     * manifested in the backend util an update is performed on this Entry.
+     *
+     * @param a_parentEntry the parent to make this Entry a child of.
+     */
+    void setParent( LdapEntry a_parentEntry )
+        throws NamingException
+    {
+		removeValues( PARENTDN_ATTR ) ;
+		addValue(PARENTDN_ATTR, a_parentEntry.getEntryDN() ) ;
+	
+		removeValues( PARENTID_ATTR ) ;
+		addValue( PARENTID_ATTR, ( ( LdapEntryImpl ) a_parentEntry )
+            .getSingleValue( ID_ATTR ) ) ;
+    }
+
+
+    /**
+     * Sets this Entry's DN modifying both the operational attribute for 
+     * tracking the user provided DN as well as the normalized DN.
+     *
+     * @param a_dn the new user provided dn to change this Entry's DN to.
+     */
+    void setEntryDN(Name a_dn)
+        throws NamingException
+    {
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("" //ProtocolModule.getMessageKey()
+                + " - LdapEntryImpl.setEntryDN() - altering entry dn from "
+                + m_normalizedDn+ " to " + a_dn) ;
+        }
+
+        // Get the old user provided Dn and remove it by removing it from
+        // this MultiMap and adding it to the m_removed MultiMap.
+        String l_oldDn = getEntryDN() ;
+        remove(DN_ATTR, l_oldDn) ;
+        if(m_isValid) {
+            m_removed.put(DN_ATTR, l_oldDn) ;
+        }
+
+        // Reparse as normalized name using schema's normalizing parser
+		m_normalizedDn =
+            m_schema.getNormalizingParser().parse(a_dn.toString()) ;
+
+        // Add unnormalized user provided Dn argument to this MultiMap and
+        // the m_added MultiMap
+        put(DN_ATTR, a_dn.toString()) ;
+        if(this.m_isValid) {
+            m_added.put(DN_ATTR, a_dn.toString()) ;
+        }
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("" //ProtocolModule.getMessageKey()
+                + " - LdapEntryImpl.setEntryDN() - dumping delta hashes "
+                + "after removing the old dn and adding the new Dn") ;
+            getLogger().debug("Added hash:\n" + this.m_added.toString()) ;
+            getLogger().debug("Removed hash:\n" + this.m_removed.toString()) ;
+        }
+    }
+
+
+    ////////////////////////////////////
+    // Overridden MultiMap Interfaces //
+    ////////////////////////////////////
+
+
+    /**
+     * Gets the user provided key form of the attribute argument first then
+     * calls the super class' containsKey with the calculated UPK.  If no
+     * UPK is found then false is returned.
+     */
+    public boolean containsKey(Object a_attrId)
+    {
+        String l_upk = getUserProvidedKey((String) a_attrId) ;
+
+        if(l_upk == null) {
+            return false ;
+        }
+
+        return super.containsKey(l_upk) ;
+    }
+
+
+    /**
+     * Gets the user provided key form of the attribute argument first then
+     * calls the super class' get with the calculated UPK.  If no UPK is found
+     * then null is returned.
+     */
+    public Object get(Object a_attrId)
+    {
+        String l_upk = getUserProvidedKey((String) a_attrId) ;
+
+        if(l_upk == null) {
+            return null ;
+        }
+
+        return super.get(l_upk) ;
+    }
+
+
+    /**
+     * Gets the user provided key form of the attribute argument first then
+     * calls the super class' put with the calculated UPK.  If there is no
+     * UPK defined it persumes that the argument is the UPK adding it to the
+     * map of canonicial forms to UPKs.  So first come first serve - meaning
+     * the first time an attribute is set to a value the text form of the
+     * attribute identifier is set as the UPK.
+     */
+    public Object put(Object a_attrId, Object a_value)
+    {
+        String l_upk = getUserProvidedKey((String) a_attrId) ;
+
+        if(l_upk == null) {
+            setUserProvidedKey((String) a_attrId) ;
+            l_upk = (String) a_attrId ;
+        }
+
+        return super.put(l_upk, a_value) ;
+    }
+
+
+    /**
+     * Gets the user provided key form of the attribute argument first then
+     * calls the super class' remove with the calculated UPK.  If no UPK is
+     * found then nothing is done.
+     */
+    public Object remove(Object a_attrId)
+    {
+        String l_upk = getUserProvidedKey((String) a_attrId) ;
+
+        if(l_upk == null) {
+            return null ;
+        }
+
+        return super.remove(l_upk) ;
+    }
+
+
+    /**
+     * Gets the user provided key form of the attribute argument first then
+     * calls the super class' remove with the calculated UPK.  If no UPK is
+     * found then nothing is done.
+     */
+    public Object remove(Object a_attrId, Object a_value)
+    {
+        String l_upk = getUserProvidedKey((String) a_attrId) ;
+
+        if(l_upk == null) {
+            return null ;
+        }
+
+        return super.remove(l_upk, a_value) ;
+    }
+
+
+    /////////////////////
+    // Utility Methods //
+    /////////////////////
+
+
+    /**
+     * Gets the canonical text normalized form of the attribute identifier. It
+     * first tests to see if the canonical for exists in the normalized
+     * attribute id cache.  If the cannonical form is there it is returned
+     * other wise it generates the normalized form and adds it to the cache.
+     * It then returns this newly generated normalized form.
+     */
+    private String getCanonicalKey(String a_attrId)
+    {
+        String l_canonical = null ;
+
+        // Now if the argument is not the key get the canonical key either
+        // from the attribute id cache or by creating it from scratch.
+        if(m_attrIdCache.containsKey(a_attrId)) {
+            l_canonical = (String) m_attrIdCache.get(a_attrId) ;
+        } else {
+            l_canonical = a_attrId.toLowerCase() ;
+            m_attrIdCache.put(a_attrId, l_canonical) ;
+            m_attrIdCache.put(l_canonical, l_canonical) ;
+        }
+
+        return l_canonical ;
+    }
+
+
+    /**
+     * Gets the original user provided key as was entered into the backend the
+     * first time.  It first presumes that the argument a_attrId is already \
+     * normalized by attempting a lookup into the normalized attribute id to
+     * user defined attribute id map.  If it finds it there the value is
+     * returned.  Otherwise it calls getCanonicalKey on the argument to get
+     * the canonical form and used the cannonical form for the same lookup. If
+     * nothing is found in the id map then null is returned.
+     */
+    private String getUserProvidedKey(String a_attrId)
+    {
+        if(m_attrIdMap.containsKey(a_attrId)) {
+            return (String) m_attrIdMap.get(a_attrId) ;
+        } else {
+            String l_canonical = getCanonicalKey(a_attrId) ;
+            if(m_attrIdMap.containsKey(l_canonical)) {
+                return (String) m_attrIdMap.get(l_canonical) ;
+            }
+        }
+
+        return null ;
+    }
+
+
+    /**
+     * Sets the user defined key in the user defined attribute Id map by making
+     * a call to getCanonicalKey to get the text normalized version of the
+     * argument String a_upk.  It uses this normalized form as the key and the
+     * argument String a_upk to create a new entry in the attribute id map.
+     */
+    private void setUserProvidedKey(String a_upk)
+    {
+        String l_canonical = getCanonicalKey(a_upk) ;
+        m_attrIdMap.put(l_canonical, a_upk) ;
+    }
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        m_log = a_logger ;
+    }
+
+
+    public boolean isDebugEnabled()
+    {
+        return m_log.isDebugEnabled() ;
+    }
+
+
+    public Logger getLogger()
+    {
+        return m_log ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/ASTNode.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/ASTNode.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,121 @@
+/*
+ * $Id: ASTNode.java,v 1.2 2003/03/13 18:27:19 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import java.util.ArrayList ;
+import java.util.Enumeration ;
+import javax.swing.tree.TreeNode ;
+
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.eve.backend.jdbm.LdapEntryImpl ;
+import org.apache.eve.backend.jdbm.index.IndexRecord;
+import java.util.Collections;
+import org.apache.eve.backend.Cursor;
+import java.util.Iterator;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.BranchNode;
+import org.apache.ldap.common.filter.LeafNode;
+import org.apache.ldap.common.filter.PresenceNode;
+import org.apache.ldap.common.filter.SubstringNode;
+
+
+/**
+ * A node representing an entry.
+ */
+public class ASTNode
+	implements TreeNode
+{
+    private final ASTNode m_parent ;
+	private final ExprNode m_exprNode ;
+    private final ArrayList m_children ;
+
+
+    public ASTNode(ASTNode a_parent, ExprNode a_exprNode)
+    {
+        m_children = new ArrayList(2) ;
+        m_exprNode = a_exprNode ;
+
+        if(a_parent == null) {
+            m_parent = this ;
+        } else {
+            m_parent = a_parent ;
+        }
+
+		try {
+            if(m_exprNode.isLeaf()) {
+                return ;
+            }
+
+            BranchNode l_branch = (BranchNode) m_exprNode ;
+            ArrayList l_exprNodes = l_branch.getChildren() ;
+            for(int ii = 0 ; ii < l_exprNodes.size(); ii++) {
+                ExprNode l_child = (ExprNode) l_exprNodes.get(ii) ;
+                m_children.add(new ASTNode(this, l_child)) ;
+            }
+        } catch(Exception e) {
+            e.printStackTrace() ;
+        }
+    }
+
+
+    public Enumeration children()
+    {
+        return Collections.enumeration(m_children) ;
+    }
+
+
+    public boolean getAllowsChildren()
+    {
+        return !m_exprNode.isLeaf() ;
+    }
+
+
+    public TreeNode getChildAt(int a_childIndex)
+    {
+		return (TreeNode) m_children.get(a_childIndex) ;
+    }
+
+
+    public int getChildCount()
+    {
+        return m_children.size() ;
+    }
+
+
+    public int getIndex(TreeNode a_child)
+    {
+        return m_children.indexOf(a_child) ;
+    }
+
+
+    public TreeNode getParent()
+    {
+        return m_parent ;
+    }
+
+
+    public boolean isLeaf()
+    {
+        return m_children.size() <= 0 ;
+    }
+
+
+    public String toString()
+    {
+        return m_exprNode.toString() ;
+    }
+
+
+    public ExprNode getExprNode()
+    {
+        return m_exprNode ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AboutDialog.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AboutDialog.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,148 @@
+/*
+ * $Id: AboutDialog.java,v 1.2 2003/03/13 18:27:20 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui;
+
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JButton;
+import javax.swing.JTextArea;
+import javax.swing.BorderFactory;
+import javax.swing.JDialog;
+import java.awt.Frame;
+import java.awt.Rectangle;
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.WindowEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class AboutDialog extends JDialog {
+    private String title = "About";
+    private String product = "ldapd-modjdbm backend";
+    private String version = "0.7";
+    private String copyright = "Copyright (c) 2003";
+    private String comments =
+        "This is the jdbm backend database viewer or introspector.\n" +
+        "Irregular behavior can be analyzed by using this tool to inspect\n" +
+        "the state of system indices and entry attributes within the backend." ;
+    private JPanel contentPane = new JPanel();
+    private JLabel prodLabel = new JLabel();
+    private JLabel verLabel = new JLabel();
+    private JLabel copLabel = new JLabel();
+    private JTextArea commentField = new JTextArea();
+    private JPanel btnPanel = new JPanel();
+    private JButton okButton = new JButton();
+    private JLabel image = new JLabel();
+    private BorderLayout formLayout = new BorderLayout();
+    private GridBagLayout contentPaneLayout = new GridBagLayout();
+    private FlowLayout btnPaneLayout = new FlowLayout();
+    private JPanel jPanel1 = new JPanel();
+    private JPanel jPanel2 = new JPanel();
+
+    /** Creates new About Dialog */
+    public AboutDialog(Frame parent, boolean modal) {
+        super(parent, modal);
+        initGUI();
+        pack();
+    }
+
+    public AboutDialog() {
+        super();
+        setModal(true);
+        initGUI();
+        pack();
+    }
+
+    /** This method is called from within the constructor to initialize the dialog. */
+    private void initGUI() {
+        addWindowListener(
+            new java.awt.event.WindowAdapter() {
+                public void windowClosing(WindowEvent evt) {
+                    closeDialog(evt);
+                }
+            });
+        getContentPane().setLayout(formLayout);
+        contentPane.setLayout(contentPaneLayout);
+        contentPane.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1), "Ldapd Project", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        prodLabel.setText(product);
+        prodLabel.setAlignmentX(0.5f);
+        contentPane.add(prodLabel,
+        new java.awt.GridBagConstraints(java.awt.GridBagConstraints.RELATIVE, java.awt.GridBagConstraints.RELATIVE,
+        java.awt.GridBagConstraints.REMAINDER, 1, 0.0, 0.0, java.awt.GridBagConstraints.NORTHWEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(5, 5, 0, 0), 5, 0));
+        verLabel.setText(version);
+        contentPane.add(verLabel,
+        new java.awt.GridBagConstraints(java.awt.GridBagConstraints.RELATIVE, java.awt.GridBagConstraints.RELATIVE,
+        java.awt.GridBagConstraints.REMAINDER, 1, 0.0, 0.0, java.awt.GridBagConstraints.NORTHWEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(5, 5, 0, 0), 0, 0));
+        copLabel.setText(copyright);
+        contentPane.add(copLabel,
+        new java.awt.GridBagConstraints(java.awt.GridBagConstraints.RELATIVE, java.awt.GridBagConstraints.RELATIVE,
+        java.awt.GridBagConstraints.REMAINDER, 1, 0.0, 0.0, java.awt.GridBagConstraints.NORTHWEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(5, 5, 0, 0), 0, 0));
+        commentField.setBackground(getBackground());
+        commentField.setForeground(copLabel.getForeground());
+        commentField.setFont(copLabel.getFont());
+        commentField.setText(comments);
+        commentField.setEditable(false);
+        commentField.setBorder(null);
+        contentPane.add(commentField,
+        new java.awt.GridBagConstraints(java.awt.GridBagConstraints.RELATIVE, java.awt.GridBagConstraints.RELATIVE,
+        java.awt.GridBagConstraints.REMAINDER, 3, 0.0, 1.0, java.awt.GridBagConstraints.NORTHWEST, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 5, 0), 0, 0));
+        image.setText("Ldapd");
+        image.setIcon(
+        new javax.swing.ImageIcon("C:/projects/ldapd-modjdbm/src/java/ldapd/server/backend/modjdbm/gui/ldapd.gif"));
+        image.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+        image.setMinimumSize(new java.awt.Dimension(98,44));
+        image.setMaximumSize(new java.awt.Dimension(98,44));
+        image.setAlignmentX(0.5f);
+        image.setBorder(javax.swing.BorderFactory.createEmptyBorder());
+        image.setPreferredSize(new java.awt.Dimension(98,44));
+        image.setSize(new java.awt.Dimension(98,200));
+        btnPanel.setLayout(btnPaneLayout);
+        okButton.setText("OK");
+        okButton.addActionListener(
+            new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    setVisible(false);
+                    dispose();
+                }
+            });
+        btnPanel.add(okButton);
+        getContentPane().add(image, BorderLayout.WEST);
+        getContentPane().add(contentPane, BorderLayout.CENTER);
+        getContentPane().add(btnPanel, BorderLayout.SOUTH);
+        getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
+        getContentPane().add(jPanel2, java.awt.BorderLayout.EAST);
+        setTitle(title);
+        setResizable(false);
+        setFont(new java.awt.Font("Dialog",java.awt.Font.BOLD,12));
+        formLayout.setHgap(15);
+        jPanel1.setMinimumSize(new java.awt.Dimension(10, 30));
+        jPanel1.setPreferredSize(new java.awt.Dimension(10, 30));
+        jPanel1.setSize(new java.awt.Dimension(564, 35));
+        jPanel2.setMinimumSize(new java.awt.Dimension(72, 165));
+        jPanel2.setPreferredSize(new java.awt.Dimension(80, 165));
+        jPanel2.setSize(new java.awt.Dimension(72, 170));
+        jPanel2.setMaximumSize(new java.awt.Dimension(80,165));
+    }
+
+    /** Closes the dialog */
+    private void closeDialog(WindowEvent evt) {
+        setVisible(false);
+        dispose();
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AnnotatedFilterTreeDialog.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/AnnotatedFilterTreeDialog.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,112 @@
+/*
+ * $Id: AnnotatedFilterTreeDialog.java,v 1.2 2003/03/13 18:27:21 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+import javax.swing.JDialog ;
+import java.awt.Frame ;
+import java.awt.event.WindowEvent ;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.JTextArea;
+import javax.swing.JButton;
+import javax.swing.tree.TreeModel;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+
+public class AnnotatedFilterTreeDialog
+    extends JDialog
+{
+    private JPanel jPanel1 = new JPanel();
+    private JTree jTree1 = new JTree();
+    private JPanel jPanel2 = new JPanel();
+    private JPanel jPanel3 = new JPanel();
+    private JTextArea jTextArea1 = new JTextArea();
+    private JScrollPane jScrollPane1 = new JScrollPane();
+    private JButton jButton1 = new JButton();
+
+    /** Creates new form JDialog */
+    public AnnotatedFilterTreeDialog(Frame parent, boolean modal) {
+        super(parent, modal);
+        initGUI();
+    }
+
+    /** This method is called from within the constructor to initialize the form. */
+    private void initGUI() {
+        addWindowListener(
+            new java.awt.event.WindowAdapter() {
+                public void windowClosing(java.awt.event.WindowEvent evt) {
+                    closeDialog(evt);
+                }
+            });
+        pack();
+        getContentPane().setLayout(new java.awt.GridBagLayout());
+        getContentPane().add(jPanel1,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 1.0, 0.1, java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(10, 5, 5, 5), 0, 0));
+        getContentPane().add(jPanel2,
+        new java.awt.GridBagConstraints(0, 1, 1, 1, 1.0, 0.8, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 5, 5), 0, 0));
+        getContentPane().add(jPanel3,
+        new java.awt.GridBagConstraints(0, 2, 1, 1, 1.0, 0.1, java.awt.GridBagConstraints.SOUTH, java.awt.GridBagConstraints.HORIZONTAL,
+        new java.awt.Insets(0, 0, 0, 0), 0, 0));
+        jPanel1.setLayout(new java.awt.BorderLayout(10, 10));
+        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1), "Search Filter", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        jPanel1.add(jTextArea1, java.awt.BorderLayout.CENTER);
+        jScrollPane1.getViewport().add(jTree1);
+        jTree1.setBounds(new java.awt.Rectangle(238,142,82,80));
+        jTextArea1.setText("");
+        jTextArea1.setEditable(false);
+        setBounds(new java.awt.Rectangle(0,0,485,414));
+        jPanel2.setLayout(new java.awt.BorderLayout());
+        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1),
+        "Filter Expression Tree", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
+        jButton1.setText("Done");
+        jButton1.setActionCommand("Done");
+		jButton1.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent a_event) {
+                AnnotatedFilterTreeDialog.this.setVisible(false) ;
+				AnnotatedFilterTreeDialog.this.dispose() ;
+            }
+        }) ;
+        jButton1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+        jButton1.setAlignmentX(0.5f);
+        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+        jPanel3.setPreferredSize(new java.awt.Dimension(79, 41));
+        jPanel3.setMinimumSize(new java.awt.Dimension(79, 41));
+        jPanel3.setSize(new java.awt.Dimension(471,35));
+        jPanel3.setToolTipText("");
+        jPanel3.add(jButton1);
+    }
+
+    /** Closes the dialog */
+    private void closeDialog(WindowEvent evt) {
+        setVisible(false);
+        dispose();
+    }
+
+
+    public void setModel(TreeModel a_model)
+    {
+        this.jTree1.setModel(a_model) ;
+    }
+
+
+    public void setFilter(String a_filter)
+    {
+        this.jTextArea1.setText(a_filter) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/BackendFrame.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/BackendFrame.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,742 @@
+/*
+ * $Id: BackendFrame.java,v 1.3 2003/03/13 18:27:22 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import java.io.File ;
+
+import javax.swing.JTree ;
+import javax.swing.JMenu ;
+import javax.swing.JTable ;
+import javax.swing.JFrame ;
+import javax.swing.JPanel ;
+import javax.swing.JLabel ;
+import javax.swing.JMenuBar ;
+import javax.swing.JMenuItem ;
+import javax.swing.JSplitPane ;
+import javax.swing.JSeparator ;
+import javax.swing.JScrollPane ;
+import javax.swing.JTabbedPane ;
+import javax.swing.JFileChooser ;
+import javax.swing.tree.TreePath ;
+import javax.swing.tree.TreeModel ;
+import javax.swing.tree.DefaultTreeModel ;
+import javax.swing.event.TreeSelectionEvent ;
+import javax.swing.event.TreeSelectionListener ;
+
+import java.awt.Dimension ;
+import java.awt.BorderLayout ;
+import java.awt.event.ActionEvent ;
+import java.awt.event.ActionListener ;
+
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.eve.backend.jdbm.LdapEntryImpl ;
+
+import org.apache.eve.Kernel ;
+import java.util.HashMap;
+import java.awt.Toolkit;
+import org.apache.eve.backend.jdbm.search.SearchEngine;
+import org.apache.eve.backend.jdbm.JdbmModule;
+import org.apache.eve.backend.Backend;
+import org.apache.ldap.common.filter.FilterParserImpl;
+import org.apache.ldap.common.filter.FilterParser;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.FilterParserMonitorAdapter;
+
+import javax.swing.JOptionPane;
+import java.util.Iterator;
+import org.apache.eve.backend.jdbm.index.Index;
+import javax.swing.tree.TreeNode;
+import org.apache.eve.backend.jdbm.search.DefaultOptimizer;
+import javax.swing.JTextArea;
+import java.util.Stack;
+import java.math.BigInteger;
+import org.apache.eve.backend.jdbm.index.IndexRecord;
+import javax.swing.table.DefaultTableModel;
+import org.apache.eve.backend.Cursor;
+import org.apache.avalon.framework.logger.LogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+
+
+public class BackendFrame
+    extends JFrame
+    implements LogEnabled
+{
+    private JLabel statusBar = new JLabel("Ready") ;
+    private JPanel m_mainPnl = new JPanel() ;
+    private JSplitPane m_splitPane = new JSplitPane() ;
+    private JTabbedPane m_tabbedPane = new JTabbedPane() ;
+    private JPanel m_entryPnl = new JPanel() ;
+    private JPanel m_idxPnl = new JPanel() ;
+    private JScrollPane m_treePane = new JScrollPane() ;
+    private JTree m_tree = new JTree() ;
+    private JScrollPane m_entryPane = new JScrollPane() ;
+    private JTable m_entryTbl = new JTable() ;
+    private JScrollPane m_idxPane = new JScrollPane() ;
+    private JTable m_idxTbl = new JTable() ;
+    private JMenu m_searchMenu = new JMenu();
+    private JMenuItem m_annotate = new JMenuItem();
+    private JMenuItem m_run = new JMenuItem();
+    private JMenuItem m_debug = new JMenuItem();
+    private JMenu m_indices = new JMenu();
+    private Database m_database = null ;
+    private boolean m_doCleanUp = false ;
+    private HashMap m_nodes = new HashMap() ;
+    private EntryNode m_root = null ;
+    private Kernel m_kernel = null ;
+    private Logger m_logger = null ;
+
+    /**
+     * Creates new form JFrame
+     */
+    public BackendFrame() {
+        initGUI() ;
+        pack() ;
+    }
+
+
+    /**
+     * This method is called from within the constructor to initialize the form
+     */
+    private void initGUI() {
+        m_mainPnl.setBorder(null) ;
+        m_mainPnl.setLayout(new java.awt.BorderLayout()) ;
+        m_mainPnl.add(m_splitPane, java.awt.BorderLayout.CENTER) ;
+        m_splitPane.add(m_tabbedPane, javax.swing.JSplitPane.RIGHT) ;
+        m_splitPane.add(m_treePane, javax.swing.JSplitPane.LEFT) ;
+        m_tabbedPane.add(m_entryPnl, "Entry Attributes") ;
+        m_tabbedPane.add(m_idxPnl, "Entry Indices") ;
+
+        m_entryPnl.setLayout(new java.awt.BorderLayout());
+        m_entryPnl.add(m_entryPane, java.awt.BorderLayout.CENTER);
+
+        m_idxPnl.setLayout(new java.awt.BorderLayout());
+        m_idxPnl.add(m_idxPane, java.awt.BorderLayout.CENTER);
+
+        getContentPane().setLayout(new java.awt.BorderLayout());
+        JPanel content = new JPanel();
+        content.setPreferredSize(new java.awt.Dimension(798, 461));
+        content.setLayout(new java.awt.BorderLayout());
+        content.setBorder(javax.swing.BorderFactory.createEtchedBorder());
+        content.add(m_mainPnl, java.awt.BorderLayout.NORTH);
+        getContentPane().add(content, BorderLayout.CENTER);
+        // set title
+        setTitle("Jdbm DB Backend Viewer");
+        // add status bar
+        getContentPane().add(statusBar, BorderLayout.SOUTH);
+        // add menu bar
+        JMenuBar menuBar = new JMenuBar();
+        JMenu m_backendMenu = new JMenu("File");
+        m_backendMenu.setMnemonic('F');
+        // create Exit menu item
+        JMenuItem m_exit = new JMenuItem("Exit");
+        m_exit.setMnemonic('E');
+        m_exit.setBackground(new java.awt.Color(205,205,205));
+        m_exit.addActionListener(
+            new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    exitForm() ;
+                }
+            });
+        // create About menu item
+        JMenu m_helpMenu = new JMenu("Help");
+        m_helpMenu.setMnemonic('H');
+        JMenuItem m_about = new JMenuItem("About");
+        m_about.setMnemonic('A');
+        m_about.setBackground(new java.awt.Color(205,205,205));
+        m_about.addActionListener(
+            new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    AboutDialog aboutDialog = new AboutDialog (BackendFrame.this, true);
+                    Dimension frameSize = getSize();
+                    Dimension aboutSize = aboutDialog.getPreferredSize();
+                    int x = getLocation().x + (frameSize.width - aboutSize.width) / 2;
+                    int y = getLocation().y + (frameSize.height - aboutSize.height) / 2;
+                    if (x < 0) x = 0;
+                    if (y < 0) y = 0;
+                    aboutDialog.setLocation(x, y);
+                    aboutDialog.setVisible(true);
+                }
+            });
+        m_helpMenu.setBackground(new java.awt.Color(205,205,205));
+        m_helpMenu.add(m_about);
+        // create Open menu item
+        String l_startPath = null ;
+        if(File.separatorChar == '/') {
+            l_startPath = "../projects/ldapd-test" ;
+        } else {
+            l_startPath = "..\\projects\\ldapd-test" ;
+        }
+
+        final JFileChooser fc = new JFileChooser(l_startPath);
+        JMenuItem m_open = new JMenuItem("Open");
+        m_open.setMnemonic('O');
+        m_open.setName("Open");
+        m_open.setActionCommand("Open");
+        m_open.setBackground(new java.awt.Color(205,205,205));
+        m_open.addActionListener(
+            new java.awt.event.ActionListener() {
+                public void actionPerformed(java.awt.event.ActionEvent e) {
+                    int returnVal = fc.showOpenDialog(BackendFrame.this);
+                    if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
+                        File file = fc.getSelectedFile() ;
+                        try {
+							loadDatabase("ldapd.test.Harness", file.getParent()) ;
+                        } catch(Exception ex) {
+                            ex.printStackTrace() ;
+                        }
+                    } else {
+                        // Write your code here what to do if user has canceled Open dialog
+                    }
+                }
+            });
+        m_backendMenu.setName("Backend");
+        m_backendMenu.setBackground(new java.awt.Color(205,205,205));
+        m_backendMenu.add(m_open);
+        // create Save menu item
+        // create Print menu item
+        m_backendMenu.add(m_exit);
+        menuBar.setBackground(new java.awt.Color(196,197,203));
+        menuBar.add(m_backendMenu);
+        menuBar.add(m_searchMenu);
+        menuBar.add(m_indices);
+        menuBar.add(m_helpMenu);
+        // sets menu bar
+        setJMenuBar(menuBar);
+        setBounds(new java.awt.Rectangle(0, 0, 802, 515));
+        setSize(new java.awt.Dimension(802,515));
+        setResizable(true);
+        addWindowListener(
+            new java.awt.event.WindowAdapter() {
+                public void windowClosing(java.awt.event.WindowEvent evt) {
+                    exitForm() ;
+                }
+            });
+        m_treePane.getViewport().add(m_tree);
+        m_tree.setBounds(new java.awt.Rectangle(6,184,82,80));
+        m_tree.setShowsRootHandles(true);
+        m_tree.setToolTipText("Jdbm DB DIT");
+        m_tree.setScrollsOnExpand(true) ;
+        m_tree.getSelectionModel().addTreeSelectionListener(
+            new TreeSelectionListener() {
+                public void valueChanged(TreeSelectionEvent e) {
+                    TreePath l_path = e.getNewLeadSelectionPath() ;
+
+                    if(l_path == null) {
+                        return ;
+                    }
+
+                    Object l_last = l_path.getLastPathComponent() ;
+                    try {
+                        if(l_last instanceof EntryNode) {
+                            displayEntry(((EntryNode) l_last).getLdapEntry()) ;
+                        }
+                    } catch(Exception ex) {
+                        ex.printStackTrace() ;
+                    }
+                }
+        }) ;
+
+        m_entryPane.getViewport().add(m_entryTbl);
+        m_entryTbl.setBounds(new java.awt.Rectangle(321,103,32,32));
+
+        m_idxPane.getViewport().add(m_idxTbl);
+        m_idxTbl.setBounds(new java.awt.Rectangle(429,134,32,32));
+
+        m_treePane.setSize(new java.awt.Dimension(285, 435));
+        m_treePane.setPreferredSize(new java.awt.Dimension(285, 403));
+        m_searchMenu.setText("Search") ;
+        m_searchMenu.setName("Search") ;
+        m_searchMenu.setBackground(new java.awt.Color(205,205,205));
+        m_searchMenu.add(m_run) ;
+        m_searchMenu.add(m_debug) ;
+        m_searchMenu.add(m_annotate) ;
+
+        ActionListener l_searchHandler = new ActionListener()
+        {
+            public void actionPerformed(ActionEvent an_event) {
+                System.out.println("action command = " + an_event.getActionCommand()) ;
+				doFilterDialog(an_event.getActionCommand()) ;
+            }
+        } ;
+
+        m_annotate.setText(FilterDialog.ANNOTATE_MODE) ;
+        m_annotate.setName(FilterDialog.ANNOTATE_MODE) ;
+        m_annotate.setActionCommand(FilterDialog.ANNOTATE_MODE) ;
+        m_annotate.setBackground(new java.awt.Color(205,205,205));
+        m_annotate.addActionListener(l_searchHandler) ;
+
+        m_run.setText(FilterDialog.RUN_MODE) ;
+        m_run.setName(FilterDialog.RUN_MODE) ;
+        m_run.setActionCommand(FilterDialog.RUN_MODE) ;
+        m_run.setBackground(new java.awt.Color(205,205,205));
+        m_run.addActionListener(l_searchHandler) ;
+
+        m_debug.setText(FilterDialog.DEBUG_MODE) ;
+        m_debug.setName(FilterDialog.DEBUG_MODE) ;
+        m_debug.setActionCommand(FilterDialog.DEBUG_MODE) ;
+        m_debug.setBackground(new java.awt.Color(205,205,205));
+        m_debug.addActionListener(l_searchHandler) ;
+
+        m_indices.setText("Indices") ;
+        m_indices.setName("Indices") ;
+        m_indices.setBackground(new java.awt.Color(205,205,205));
+    }
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        m_logger = a_logger ;
+    }
+
+
+    public void launch()
+    {
+        //Center the frame on screen
+        Dimension l_screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension l_frameSize = getSize() ;
+        l_frameSize.height = ((l_frameSize.height > l_screenSize.height)
+            ? l_screenSize.height : l_frameSize.height);
+        l_frameSize.width = ((l_frameSize.width > l_screenSize.width)
+            ? l_screenSize.width : l_frameSize.width);
+        setLocation((l_screenSize.width - l_frameSize.width) / 2,
+            (l_screenSize.height - l_frameSize.height) / 2);
+        setVisible(true) ;
+    }
+
+
+    /**
+     * Exit the Application
+     */
+    private void exitForm() {
+        this.setEnabled(false) ;
+        this.setVisible(false) ;
+        this.dispose() ;
+
+        if(m_doCleanUp && m_database != null) {
+            m_database.sync() ;
+            m_database.close() ;
+	        System.exit(0) ;
+        }
+    }
+
+
+    public void doFilterDialog(final String a_mode)
+    {
+        final FilterDialog l_dialog = new FilterDialog(a_mode, this, true) ;
+
+        if(this.m_tree.getSelectionModel().getSelectionPath() != null) {
+            TreePath l_path = m_tree.getSelectionModel().getSelectionPath() ;
+            Object l_last = l_path.getLastPathComponent() ;
+            String l_base = null ;
+            if(l_last instanceof EntryNode) {
+                LdapEntryImpl l_entry = ((EntryNode) l_last).getLdapEntry() ;
+                l_base = l_entry.getEntryDN() ;
+            } else {
+                l_base = m_database.getSuffix().toString() ;
+            }
+
+            l_dialog.setBase(l_base) ;
+        } else {
+            l_dialog.setBase(m_database.getSuffix().toString()) ;
+        }
+
+        l_dialog.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent an_event) {
+                String l_cmd = an_event.getActionCommand() ;
+
+                try {
+                    if(l_cmd.equals(FilterDialog.SEARCH_CMD)) {
+                        if(a_mode == FilterDialog.RUN_MODE) {
+                            doRun(l_dialog.getFilter(), l_dialog.getScope(),
+                                l_dialog.getBase(), l_dialog.getLimit()) ;
+                        } else if(a_mode == FilterDialog.DEBUG_MODE) {
+                            doDebug(l_dialog.getFilter(), l_dialog.getScope(),
+                                 l_dialog.getBase(), l_dialog.getLimit()) ;
+                        } else if(a_mode == FilterDialog.ANNOTATE_MODE) {
+                            if(doAnnotate(l_dialog.getFilter())) {
+                                // continue
+                            } else {
+                                // We failed don't loose users filter buf
+                                // allow user to make edits.
+                                return ;
+                            }
+                        } else {
+                            throw new RuntimeException("Unrecognized mode.") ;
+                        }
+                    } else if(l_cmd.equals(FilterDialog.CANCEL_CMD)) {
+                        // Do nothing! Just exit dialog.
+                    } else {
+                        throw new
+                            RuntimeException("Unrecognized FilterDialog command: "
+                                + l_cmd) ;
+                    }
+                } catch(Exception e) {
+                    e.printStackTrace() ;
+                }
+
+				l_dialog.setVisible(false) ;
+				l_dialog.dispose() ;
+            }
+        }) ;
+
+        //Center the frame on screen
+        l_dialog.setSize(456, 256) ;
+        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension frameSize = l_dialog.getSize();
+        frameSize.height = ((frameSize.height > screenSize.height)
+            ? screenSize.height : frameSize.height);
+        frameSize.width = ((frameSize.width > screenSize.width)
+            ? screenSize.width : frameSize.width);
+        l_dialog.setLocation((screenSize.width - frameSize.width) / 2,
+            (screenSize.height - frameSize.height) / 2);
+        l_dialog.setEnabled(true) ;
+        l_dialog.setVisible(true) ;
+    }
+
+
+    public boolean doRun(String a_filter, String a_scope, String a_base,
+        String a_limit)
+        throws Exception
+    {
+        System.out.println("Search attempt using filter '" + a_filter + "' "
+            + "with scope '" + a_scope + "' and a return limit of '" + a_limit
+            + "'") ;
+        SearchEngine l_engine = new SearchEngine() ;
+        l_engine.enableLogging(m_logger) ;
+        FilterParser l_parser = new FilterParserImpl() ;
+        l_parser.setFilterParserMonitor( new FilterParserMonitorAdapter() ) ;
+        ExprNode l_root = null ;
+
+        try {
+            l_root = l_parser.parse(a_filter) ;
+        } catch(Exception e) {
+            JTextArea l_text = new JTextArea() ;
+            String l_msg = e.getMessage() ;
+
+            if(l_msg.length() > 1024) {
+                l_msg = l_msg.substring(0, 1024) + "\n. . . truncated . . ." ;
+            }
+
+            l_text.setText(l_msg) ;
+            l_text.setEnabled(false) ;
+            JOptionPane.showMessageDialog(null, l_text, "Syntax Error",
+                JOptionPane.ERROR_MESSAGE) ;
+            return false ;
+        }
+
+        int l_scope = -1 ;
+
+        if(a_scope == FilterDialog.BASE_SCOPE) {
+	        l_scope = Backend.BASE_SCOPE ;
+        } else if(a_scope == FilterDialog.SINGLE_SCOPE) {
+            l_scope = Backend.SINGLE_SCOPE ;
+        } else if(a_scope == FilterDialog.SUBTREE_SCOPE) {
+            l_scope = Backend.SUBTREE_SCOPE ;
+        } else {
+            throw new RuntimeException("Unexpected scope parameter: " +
+                a_scope) ;
+        }
+
+        int l_limit = Integer.MAX_VALUE ;
+        if(!a_limit.equals(FilterDialog.UNLIMITED)) {
+            l_limit = Integer.parseInt(a_limit) ;
+        }
+
+        Cursor l_cursor =
+            l_engine.search(m_database, l_root, a_base, l_scope) ;
+        String [] l_cols = new String [2] ;
+        l_cols[0] = "id" ;
+        l_cols[1] = "dn" ;
+        DefaultTableModel l_tableModel = new DefaultTableModel(l_cols, 0) ;
+        Object [] l_row = new Object[2] ;
+        int l_count = 0 ;
+        while(l_cursor.hasMore() && l_count < l_limit) {
+            IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+            l_row[0] = l_rec.getEntryId() ;
+            l_row[1] = m_database.getEntryDn((BigInteger) l_row[0]) ;
+            l_tableModel.addRow(l_row) ;
+            l_count++ ;
+        }
+
+        SearchResultDialog l_results = new SearchResultDialog(this, false) ;
+        StringBuffer l_buf = new StringBuffer() ;
+        l_buf.append("base: ").append(a_base).append('\n') ;
+        l_buf.append("scope: ").append(a_scope).append('\n') ;
+        l_buf.append("limit: ").append(a_limit).append('\n') ;
+        l_buf.append("total: ").append(l_count).append('\n') ;
+        l_buf.append("filter:\n").append(a_filter).append('\n') ;
+        l_results.setFilter(l_buf.toString()) ;
+
+	    TreeNode l_astRoot = new ASTNode(null, l_root) ;
+	    TreeModel l_treeModel = new DefaultTreeModel(l_astRoot, true) ;
+        l_results.setTreeModel(l_treeModel) ;
+        l_results.setTableModel(l_tableModel) ;
+        l_results.setVisible(true) ;
+        return true ;
+    }
+
+
+    public void doDebug(String a_filter, String a_scope, String a_base,
+        String a_limit)
+    {
+        System.out.println("Search attempt using filter '" + a_filter + "' "
+            + "with scope '" + a_scope + "' and a return limit of '" + a_limit
+            + "'") ;
+    }
+
+
+    public void selectTreeNode(BigInteger a_id)
+    {
+        Stack l_stack = new Stack() ;
+        TreeNode l_parent = (EntryNode) m_nodes.get(a_id) ;
+        while(l_parent != null && (l_parent != l_parent.getParent())) {
+            l_stack.push(l_parent) ;
+            l_parent = l_parent.getParent() ;
+        }
+
+
+        Object [] l_comps = null ;
+
+        if(l_stack.size() == 0) {
+            l_comps = new Object[1] ;
+            l_comps[0] = m_root ;
+        } else {
+            l_comps = new Object[l_stack.size()] ;
+        }
+
+        for(int ii = 0; l_stack.size() > 0 && ii < l_comps.length; ii++) {
+            l_comps[ii] = l_stack.pop() ;
+        }
+
+        TreePath l_path = new TreePath(l_comps) ;
+        m_tree.scrollPathToVisible(l_path) ;
+        m_tree.getSelectionModel().setSelectionPath(l_path) ;
+        m_tree.validate() ;
+    }
+
+
+    public boolean doAnnotate(String a_filter)
+        throws Exception
+    {
+		FilterParser l_parser = new FilterParserImpl() ;
+        l_parser.setFilterParserMonitor( new FilterParserMonitorAdapter() );
+        ExprNode l_root = null ;
+
+        try {
+            l_root = l_parser.parse(a_filter) ;
+        } catch(Exception e) {
+            JTextArea l_text = new JTextArea() ;
+            String l_msg = e.getMessage() ;
+
+            if(l_msg.length() > 1024) {
+                l_msg = l_msg.substring(0, 1024) + "\n. . . truncated . . ." ;
+            }
+
+            l_text.setText(l_msg) ;
+            l_text.setEnabled(false) ;
+            JOptionPane.showMessageDialog(null, l_text, "Syntax Error",
+                JOptionPane.ERROR_MESSAGE) ;
+            return false ;
+        }
+
+		AnnotatedFilterTreeDialog l_treeDialog = new
+			AnnotatedFilterTreeDialog(BackendFrame.this, false) ;
+		l_treeDialog.setFilter(a_filter) ;
+
+        DefaultOptimizer l_optimizer = new DefaultOptimizer() ;
+        l_optimizer.annotate(this.m_database, l_root) ;
+		TreeNode l_astRoot = new ASTNode(null, l_root) ;
+		TreeModel l_model = new DefaultTreeModel(l_astRoot, true) ;
+		l_treeDialog.setModel(l_model) ;
+        l_treeDialog.setVisible(true) ;
+        return true ;
+    }
+
+
+    public void showIndexDialog(String a_index)
+        throws Exception
+    {
+        System.out.println("Got request to show index dialog for " + a_index) ;
+        Index l_index = (Index) m_database.getIndex(a_index) ;
+
+        if(l_index != null) {
+            IndexDialog l_dialog = new IndexDialog(this, false, l_index) ;
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Dimension frameSize = l_dialog.getSize();
+            frameSize.height = ((frameSize.height > screenSize.height)
+                ? screenSize.height : frameSize.height);
+            frameSize.width = ((frameSize.width > screenSize.width)
+                ? screenSize.width : frameSize.width);
+            l_dialog.setLocation((screenSize.width - frameSize.width) / 2,
+                (screenSize.height - frameSize.height) / 2);
+            l_dialog.setEnabled(true) ;
+            l_dialog.setVisible(true) ;
+        }
+    }
+
+
+    public void buildIndicesMenu(Database a_database)
+    {
+        ActionListener l_listener = new ActionListener()
+        {
+            public void actionPerformed(ActionEvent a_event) {
+                try {
+                    showIndexDialog(a_event.getActionCommand()) ;
+                } catch(Exception e) {
+                    e.printStackTrace() ;
+                }
+            }
+        } ;
+
+        JMenuItem l_item = null ;
+        String [] l_sdi = Database.SYS_INDICES ;
+        Iterator l_udi = a_database.getUDIAttributes() ;
+
+        for(int ii = 0; ii < l_sdi.length; ii++) {
+			l_item = new JMenuItem() ;
+            l_item.setBackground(new java.awt.Color(205,205,205));
+            m_indices.add(l_item) ;
+            l_item.setText(l_sdi[ii]) ;
+            l_item.setName(l_sdi[ii]) ;
+            l_item.setActionCommand(l_sdi[ii]) ;
+            l_item.addActionListener(l_listener) ;
+        }
+
+        m_indices.add(new JSeparator()) ;
+
+        while(l_udi.hasNext()) {
+            String l_index = (String) l_udi.next() ;
+			l_item = new JMenuItem() ;
+            l_item.setBackground(new java.awt.Color(205,205,205));
+            m_indices.add(l_item) ;
+            l_item.setText(l_index) ;
+            l_item.setName(l_index) ;
+            l_item.setActionCommand(l_index) ;
+            l_item.addActionListener(l_listener) ;
+        }
+    }
+
+
+    void displayEntry(LdapEntryImpl a_entry)
+        throws Exception
+    {
+        MultiMapModel l_model = new MultiMapModel(a_entry) ;
+        this.m_entryTbl.setModel(l_model) ;
+
+        if(m_database != null) {
+            l_model = new MultiMapModel(
+                m_database.getIndices(a_entry.getEntryID())) ;
+            this.m_idxTbl.setModel(l_model) ;
+        } else {
+            this.m_idxTbl.setModel(null) ;
+        }
+
+        this.validate() ;
+    }
+
+
+    public void loadDatabase(Database a_database)
+        throws Exception
+    {
+        m_database = a_database ;
+        m_doCleanUp = false ;
+        load() ;
+    }
+
+
+    public void loadDatabase(String a_kernelClass, String a_dirPath)
+        throws Exception
+    {
+        m_doCleanUp = true ;
+
+        m_kernel = (Kernel) Class.forName(a_kernelClass).newInstance() ;
+        m_kernel.setRoot(a_dirPath) ;
+        m_kernel.bootStrap("backend0") ;
+        m_logger = m_kernel.getLogger() ;
+        JdbmModule l_backend = (JdbmModule)
+            m_kernel.getServiceManager().lookup(JdbmModule.ROLE) ;
+        m_database = l_backend.getDatabase() ;
+        load() ;
+    }
+
+
+    private void load()
+        throws Exception
+    {
+        boolean doFiltered = false ;
+        m_nodes = new HashMap() ;
+
+        int l_option =
+            JOptionPane.showConfirmDialog(null, "Would you like to filter "
+            + "leaf nodes on load?", "Use Filter?",
+            JOptionPane.OK_CANCEL_OPTION) ;
+        doFiltered = l_option == JOptionPane.OK_OPTION ;
+
+        if(doFiltered) {
+            SearchEngine l_engine = new SearchEngine() ;
+            final FilterDialog l_dialog =
+                new FilterDialog(FilterDialog.LOAD_MODE, this, true) ;
+            l_dialog.addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    l_dialog.setVisible(false) ;
+                    l_dialog.dispose() ;
+                }
+            }) ;
+
+            l_dialog.setBase(m_database.getSuffix().toString()) ;
+            l_dialog.setScope(FilterDialog.SUBTREE_SCOPE) ;
+
+            //Center the frame on screen
+            l_dialog.setSize(456, 256) ;
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Dimension frameSize = l_dialog.getSize();
+            frameSize.height = ((frameSize.height > screenSize.height)
+                ? screenSize.height : frameSize.height);
+            frameSize.width = ((frameSize.width > screenSize.width)
+                ? screenSize.width : frameSize.width);
+            l_dialog.setLocation((screenSize.width - frameSize.width) / 2,
+                (screenSize.height - frameSize.height) / 2);
+            l_dialog.setEnabled(true) ;
+            l_dialog.setVisible(true) ;
+
+            FilterParser l_parser = new FilterParserImpl() ;
+            l_parser.setFilterParserMonitor( new FilterParserMonitorAdapter());
+            ExprNode l_exprNode = l_parser.parse(l_dialog.getFilter()) ;
+
+            int l_scope = -1 ;
+            String l_scopeStr = l_dialog.getScope() ;
+            if(l_scopeStr == FilterDialog.BASE_SCOPE) {
+                l_scope = Backend.BASE_SCOPE ;
+            } else if(l_scopeStr == FilterDialog.SINGLE_SCOPE) {
+                l_scope = Backend.SINGLE_SCOPE ;
+            } else if(l_scopeStr == FilterDialog.SUBTREE_SCOPE) {
+                l_scope = Backend.SUBTREE_SCOPE ;
+            } else {
+                throw new RuntimeException("Unrecognized scope") ;
+            }
+
+            l_exprNode =
+                l_engine.addScopeNode(l_exprNode, l_dialog.getBase(), l_scope) ;
+            m_root = new EntryNode(null, m_database,
+                m_database.getSuffixEntry(), m_nodes, l_exprNode, l_engine) ;
+        } else {
+            m_root = new EntryNode(null, m_database,
+                m_database.getSuffixEntry(), m_nodes) ;
+        }
+
+        DefaultTreeModel l_model = new DefaultTreeModel(m_root) ;
+        m_tree.setModel(l_model) ;
+        buildIndicesMenu(m_database) ;
+        if(this.isVisible()) {
+            m_tree.validate() ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/EntryNode.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/EntryNode.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,172 @@
+/*
+ * $Id: EntryNode.java,v 1.3 2003/03/13 18:27:22 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import java.util.ArrayList ;
+import java.util.Enumeration ;
+import javax.swing.tree.TreeNode ;
+
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.eve.backend.jdbm.LdapEntryImpl ;
+import org.apache.eve.backend.jdbm.index.IndexRecord;
+import java.util.Collections;
+import org.apache.eve.backend.Cursor;
+import java.util.Iterator;
+import java.util.HashMap;
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.eve.backend.jdbm.search.SearchEngine;
+
+
+/**
+ * A node representing an entry.
+ */
+public class EntryNode
+	implements TreeNode
+{
+    private final Database m_db ;
+    private final EntryNode m_parent ;
+	private final LdapEntryImpl m_entry ;
+    private final ArrayList m_children ;
+
+
+    public EntryNode(EntryNode a_parent, Database a_db, LdapEntryImpl a_entry,
+        HashMap a_map)
+    {
+        this(a_parent, a_db, a_entry, a_map, null, null) ;
+    }
+
+
+    public EntryNode(EntryNode a_parent, Database a_db, LdapEntryImpl a_entry,
+        HashMap a_map, ExprNode a_exprNode, SearchEngine a_engine)
+    {
+        m_db = a_db ;
+		m_entry = a_entry ;
+        m_children = new ArrayList() ;
+
+        if(a_parent == null) {
+            m_parent = this ;
+        } else {
+            m_parent = a_parent ;
+        }
+
+		try {
+            ArrayList l_records = new ArrayList() ;
+            Cursor l_cursor = m_db.getChildren(m_entry.getEntryID()) ;
+            while(l_cursor.hasMore()) {
+                IndexRecord l_old = (IndexRecord) l_cursor.next() ;
+                IndexRecord l_new = new IndexRecord() ;
+                l_new.setEntryId(l_old.getEntryId()) ;
+                l_new.setIndexKey(l_old.getIndexKey()) ;
+                l_records.add(l_new) ;
+            }
+            l_cursor.close() ;
+
+            Iterator l_list = l_records.iterator() ;
+            while(l_list.hasNext()) {
+                IndexRecord l_rec = (IndexRecord) l_list.next() ;
+
+                // Avoids root node which is both a parent and child of itself.
+                if(l_rec.getEntryId().equals(m_entry.getEntryID())) {
+                    continue ;
+                }
+
+                if(a_engine != null && a_exprNode != null) {
+                    if(m_db.getChildCount(l_rec.getEntryId()) == 0) {
+                        if(a_engine.assertExpression(m_db, a_exprNode,
+                            l_rec.getEntryId()))
+                        {
+                            LdapEntryImpl l_entry = m_db.read(l_rec.getEntryId()) ;
+                            EntryNode l_child =
+                                new EntryNode(this, m_db, l_entry, a_map,
+                                a_exprNode, a_engine) ;
+                            m_children.add(l_child) ;
+                        } else {
+                            continue ;
+                        }
+                    } else {
+                        LdapEntryImpl l_entry = m_db.read(l_rec.getEntryId()) ;
+                        EntryNode l_child = new EntryNode(this, m_db, l_entry,
+                            a_map, a_exprNode, a_engine) ;
+                        m_children.add(l_child) ;
+                    }
+                } else {
+                    LdapEntryImpl l_entry = m_db.read(l_rec.getEntryId()) ;
+                    EntryNode l_child =
+                        new EntryNode(this, m_db, l_entry, a_map) ;
+                    m_children.add(l_child) ;
+                }
+            }
+        } catch(Exception e) {
+            e.printStackTrace() ;
+        }
+
+        a_map.put(a_entry.getEntryID(), this) ;
+    }
+
+
+    public Enumeration children()
+    {
+        return Collections.enumeration(m_children) ;
+    }
+
+
+    public boolean getAllowsChildren()
+    {
+        return true ;
+    }
+
+
+    public TreeNode getChildAt(int a_childIndex)
+    {
+		return (TreeNode) m_children.get(a_childIndex) ;
+    }
+
+
+    public int getChildCount()
+    {
+        return m_children.size() ;
+    }
+
+
+    public int getIndex(TreeNode a_child)
+    {
+        return m_children.indexOf(a_child) ;
+    }
+
+
+    public TreeNode getParent()
+    {
+        return m_parent ;
+    }
+
+
+    public boolean isLeaf()
+    {
+        return m_children.size() <= 0 ;
+    }
+
+
+    public String toString()
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+        l_buf.append(m_entry.getEntryDN()) ;
+        if(m_children.size() > 0) {
+            l_buf.append(" [").append(m_children.size()).append(']') ;
+        }
+        return l_buf.toString() ;
+    }
+
+
+    public LdapEntryImpl getLdapEntry()
+    {
+        return m_entry ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/FilterDialog.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/FilterDialog.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,273 @@
+/*
+ * $Id: FilterDialog.java,v 1.2 2003/03/13 18:27:23 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import javax.swing.JLabel ;
+import javax.swing.JFrame ;
+import javax.swing.JPanel ;
+import javax.swing.JDialog ;
+import javax.swing.JButton ;
+import javax.swing.JComboBox ;
+import javax.swing.JTextArea ;
+import javax.swing.JTextField ;
+import javax.swing.BorderFactory ;
+import javax.swing.border.TitledBorder ;
+
+import java.awt.Font ;
+import java.awt.Color ;
+import java.awt.Insets ;
+import java.awt.Dimension ;
+import java.awt.FlowLayout ;
+import java.awt.BorderLayout ;
+import java.awt.GridBagLayout ;
+import java.awt.event.WindowEvent ;
+import java.awt.GridBagConstraints ;
+import java.awt.event.WindowAdapter ;
+import java.awt.event.ActionListener;
+
+import javax.swing.JScrollPane;
+
+
+public class FilterDialog
+    extends JDialog
+{
+	public static final String RUN_MODE = "Run" ;
+    public static final String LOAD_MODE = "Load" ;
+    public static final String DEBUG_MODE = "Debug" ;
+	public static final String ANNOTATE_MODE = "Annotate" ;
+
+    public static final String UNLIMITED = "Unlimited" ;
+
+	public static final String BASE_SCOPE = "Base Object" ;
+	public static final String SINGLE_SCOPE = "Single Level" ;
+	public static final String SUBTREE_SCOPE = "Subtree Level" ;
+
+    public static final String LOAD_CMD = "Load" ;
+    public static final String SEARCH_CMD = "Search" ;
+    public static final String CANCEL_CMD = "Cancel" ;
+
+    private JPanel m_northPnl = new JPanel() ;
+    private JPanel m_centerPnl = new JPanel() ;
+    private JTextArea m_filterText = new JTextArea() ;
+    private JLabel m_scopeLbl = new JLabel() ;
+    private JComboBox m_scopeChoice = new JComboBox() ;
+    private JLabel m_limitLbl = new JLabel() ;
+    private JTextField m_limitField = new JTextField() ;
+    private JPanel m_southPnl = new JPanel() ;
+    private JButton m_searchBut = new JButton() ;
+    private JButton m_cancelBut = new JButton() ;
+    private JScrollPane m_scrollPane = new JScrollPane() ;
+    private final String m_mode ;
+    private JTextField m_baseText = new JTextField();
+    private JPanel m_basePnl = new JPanel();
+    private JLabel jLabel1 = new JLabel();
+
+    /** Creates new form JDialog */
+    public FilterDialog(String a_mode, JFrame parent, boolean modal)
+    {
+        super(parent, modal) ;
+        m_mode = a_mode ;
+        initGUI() ;
+    }
+
+
+	public void addActionListener(ActionListener l_listener)
+    {
+        m_searchBut.addActionListener(l_listener) ;
+        m_cancelBut.addActionListener(l_listener) ;
+    }
+
+
+
+	/**
+     * This method is called from within the constructor to initialize the form
+     */
+    private void initGUI() {
+        m_baseText.setText("");
+        addWindowListener(
+            new WindowAdapter() {
+                public void windowClosing(WindowEvent evt) {
+                    closeDialog(evt);
+                }
+            }) ;
+        pack() ;
+
+        getContentPane().setLayout(new java.awt.GridBagLayout()) ;
+        getContentPane().add(m_northPnl,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 0.9, 0.0, java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 6, 0), 0, 0));
+        getContentPane().add(m_centerPnl,
+        new GridBagConstraints(0, 1, 1, 1, 0.9, 0.9,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+        new Insets(10, 10, 10, 10), 0, 0));
+        getContentPane().add(m_southPnl,
+	        new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
+        	GridBagConstraints.SOUTH, GridBagConstraints.BOTH,
+    	    new Insets(0, 0, 2, 0), 0, 0)) ;
+        m_northPnl.setLayout(new GridBagLayout()) ;
+        m_northPnl.setBorder(null) ;
+        m_northPnl.add(m_scopeLbl,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 0.2, 0.0, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(5, 0, 5, 0), 0, 0));
+        m_northPnl.add(m_scopeChoice,
+        new java.awt.GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.HORIZONTAL,
+        new java.awt.Insets(9, 0, 7, 5), 0, 0));
+        m_northPnl.add(m_limitLbl,
+	        new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
+            GridBagConstraints.CENTER, GridBagConstraints.NONE,
+        	new Insets(5, 10, 5, 5), 0, 0)) ;
+        m_northPnl.add(m_limitField,
+        new java.awt.GridBagConstraints(3, 0, 1, 1, 1.0, 0.0, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.HORIZONTAL,
+        new java.awt.Insets(11, 0, 9, 10), 0, 0));
+        m_northPnl.add(m_basePnl,
+        new java.awt.GridBagConstraints(0, 1, 4, 1, 0.0, 0.0, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 10, 5, 10), 0, 0));
+        m_filterText.setText("") ;
+        m_filterText.setBorder(null) ;
+        m_centerPnl.setLayout(new BorderLayout()) ;
+        m_centerPnl.setBorder(BorderFactory.createTitledBorder(
+            BorderFactory.createLineBorder(
+        		new Color(153, 153, 153), 1), "Search Filter",
+                TitledBorder.LEADING, TitledBorder.TOP,
+        		new Font("SansSerif", 0, 14), new Color(60, 60, 60))) ;
+        m_scrollPane.getViewport().add(m_filterText);
+        m_centerPnl.add(m_scrollPane, BorderLayout.CENTER) ;
+        m_scopeLbl.setText("Scope:") ;
+        m_scopeLbl.setFont(new java.awt.Font("Dialog", java.awt.Font.PLAIN, 14));
+        m_scopeChoice.setSize(new java.awt.Dimension(115, 25));
+        m_scopeChoice.setMaximumSize(new Dimension(32767,25)) ;
+        m_scopeChoice.setMinimumSize(new java.awt.Dimension(115, 25));
+        m_scopeChoice.setPreferredSize(new Dimension(115, 25)) ;
+		m_scopeChoice.addItem(BASE_SCOPE) ;
+		m_scopeChoice.addItem(SINGLE_SCOPE) ;
+		m_scopeChoice.addItem(SUBTREE_SCOPE) ;
+
+        m_limitLbl.setText("Limit:") ;
+        m_limitField.setText("Unlimited") ;
+        m_limitField.setHorizontalAlignment(JTextField.CENTER) ;
+        m_southPnl.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 5)) ;
+        m_southPnl.add(m_searchBut) ;
+
+        if(this.m_mode != LOAD_MODE) {
+            m_searchBut.setText(SEARCH_CMD); ;
+            m_searchBut.setActionCommand(SEARCH_CMD) ;
+            m_southPnl.add(m_cancelBut) ;
+        } else {
+            m_searchBut.setText(LOAD_CMD); ;
+            m_searchBut.setActionCommand(LOAD_CMD) ;
+        }
+
+        m_cancelBut.setText(CANCEL_CMD); ;
+        m_cancelBut.setActionCommand(CANCEL_CMD) ;
+        setBounds(new java.awt.Rectangle(0,0,595,331));
+        m_basePnl.setLayout(new java.awt.GridBagLayout());
+        m_basePnl.add(jLabel1,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(0, 0, 0, 0), 0, 0));
+        m_basePnl.add(m_baseText,
+        new java.awt.GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, java.awt.GridBagConstraints.EAST, java.awt.GridBagConstraints.HORIZONTAL,
+        new java.awt.Insets(5, 5, 5, 0), 0, 0));
+        jLabel1.setText("Search Base:");
+        jLabel1.setFont(new java.awt.Font("SansSerif", java.awt.Font.PLAIN, 14));
+
+        if(m_mode == RUN_MODE) {
+	        setTitle("Search Filter Dialog: Execute mode") ;
+        } else if(m_mode == LOAD_MODE) {
+            setTitle("Search Filter Dialog: Load mode") ;
+        } else if(m_mode == DEBUG_MODE) {
+	        setTitle("Search Filter Dialog: Debug mode") ;
+        } else if(m_mode == ANNOTATE_MODE) {
+	        setTitle("Search Filter Dialog: Annotate mode") ;
+            this.m_scopeChoice.setEnabled(false) ;
+            this.m_limitField.setEnabled(false) ;
+            this.m_baseText.setEnabled(false) ;
+        } else {
+            throw new RuntimeException("Unrecognized mode.") ;
+        }
+    }
+
+
+    /**
+     * Closes the dialog
+     */
+    public void closeDialog(WindowEvent evt)
+    {
+        setVisible(false) ;
+        dispose() ;
+    }
+
+
+	public String getScope()
+    {
+		int l_selected = m_scopeChoice.getSelectedIndex() ;
+        return (String) m_scopeChoice.getItemAt(l_selected) ;
+    }
+
+
+    /*
+	public int getScope()
+    {
+		int l_selected = m_scopeChoice.getSelectedIndex() ;
+        String l_scope = (String) m_scopeChoice.getItemAt(l_selected) ;
+
+		if(l_scope == BASE_SCOPE) {
+			return Backend.BASE_SCOPE ;
+        } else if(l_scope == SINGLE_SCOPE) {
+            return Backend.SINGLE_SCOPE ;
+        } else if(l_scope == SUBTREE_SCOPE) {
+            return Backend.SUBTREE_SCOPE ;
+        }
+
+        throw new RuntimeException("Unexpected scope parameter: " + l_scope) ;
+    }
+	*/
+
+    public String getLimit()
+    {
+		return m_limitField.getText() ;
+    }
+
+/*
+    public String getLimit()
+    {
+        String l_limit = m_limitField.getText() ;
+
+		if(l_limit.equals(UNLIMITED)) {
+            return -1 ;
+        }
+
+        return Integer.parseInt(l_limit) ;
+    }
+*/
+
+    public String getFilter()
+    {
+		return this.m_filterText.getText() ;
+    }
+
+
+    public void setBase(String a_base)
+    {
+        this.m_baseText.setText(a_base) ;
+    }
+
+
+    public void setScope(String a_scope)
+    {
+        this.m_scopeChoice.setSelectedItem(a_scope) ;
+    }
+
+
+    public String getBase()
+    {
+        return this.m_baseText.getText() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/IndexDialog.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/IndexDialog.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,256 @@
+/*
+ * $Id: IndexDialog.java,v 1.3 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+package org.apache.eve.backend.jdbm.gui;
+
+import javax.swing.JDialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import javax.swing.JTabbedPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
+import javax.swing.JComboBox;
+import javax.swing.DefaultComboBoxModel;
+import org.apache.eve.backend.jdbm.index.Index;
+import org.apache.eve.backend.Cursor;
+import javax.swing.JOptionPane;
+import org.apache.regexp.RE;
+import org.apache.eve.backend.jdbm.index.IndexRecord;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import org.apache.avalon.framework.ExceptionUtil;
+import javax.swing.JTextArea;
+import org.apache.ldap.common.util.StringTools;
+
+public class IndexDialog extends JDialog
+{
+    public static final String DEFAULT_CURSOR = "Default" ;
+    public static final String EQUALITY_CURSOR = "Equality" ;
+    public static final String GREATER_CURSOR = "Greater" ;
+    public static final String LESS_CURSOR = "Less" ;
+    public static final String REGEX_CURSOR = "Regex" ;
+
+    private Panel m_mainPnl = new Panel();
+    private JTabbedPane m_tabbedPane = new JTabbedPane();
+    private JPanel m_listPnl = new JPanel();
+    private JPanel m_cursorPnl = new JPanel();
+    private JPanel m_resultsPnl = new JPanel();
+    private JScrollPane jScrollPane2 = new JScrollPane();
+    private JTable m_resultsTbl = new JTable();
+    private JPanel m_buttonPnl = new JPanel();
+    private JButton m_doneBut = new JButton();
+    private JLabel jLabel1 = new JLabel();
+    private JTextField m_keyText = new JTextField();
+    private JLabel jLabel2 = new JLabel();
+    private JComboBox m_cursorType = new JComboBox();
+    private JButton m_scanBut = new JButton();
+    private Index m_index = null ;
+
+    /** Creates new form JDialog */
+    public IndexDialog(Frame parent, boolean modal, Index a_index)
+    {
+        super(parent, modal) ;
+        m_index = a_index ;
+        initGUI() ;
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the
+     * form.
+     */
+    private void initGUI()
+    {
+        addWindowListener(
+        new java.awt.event.WindowAdapter()
+        {
+            public void windowClosing(java.awt.event.WindowEvent evt)
+            {
+                closeDialog() ;
+            }
+        });
+        pack() ;
+        setTitle("Index On Attribute '" + m_index.getAttribute() + "'") ;
+        setBounds(new java.awt.Rectangle(0, 0, 512, 471));
+        getContentPane().add(m_mainPnl, java.awt.BorderLayout.CENTER);
+        m_mainPnl.setLayout(new java.awt.BorderLayout());
+        m_mainPnl.add(m_tabbedPane, java.awt.BorderLayout.CENTER);
+        m_tabbedPane.add(m_listPnl, "Listing");
+        m_listPnl.setLayout(new java.awt.GridBagLayout());
+        m_listPnl.add(m_cursorPnl,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 1.0, 0.15, java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(15, 0, 30, 0), 0, 0));
+        m_listPnl.add(m_resultsPnl,
+        new java.awt.GridBagConstraints(0, 1, 1, 1, 1.0, 0.8, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(0, 0, 0, 0), 0, 0));
+        m_listPnl.add(m_buttonPnl,
+        new java.awt.GridBagConstraints(0, 2, 1, 1, 1.0, 0.05, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(0, 0, 0, 0), 0, 0));
+        m_cursorPnl.setLayout(new java.awt.GridBagLayout());
+        m_cursorPnl.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1),
+        "Display Cursor Constraints", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        m_cursorPnl.add(jLabel1,
+        new java.awt.GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(0, 15, 0, 10), 0, 0));
+        m_cursorPnl.add(m_keyText,
+        new java.awt.GridBagConstraints(1, 1, 1, 1, 0.4, 0.0, java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 5, 236), 0, 0));
+        m_cursorPnl.add(jLabel2,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(0, 15, 0, 10), 0, 0));
+        m_cursorPnl.add(m_cursorType,
+        new java.awt.GridBagConstraints(1, 0, 1, 1, 0.4, 0.0, java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE,
+        new java.awt.Insets(5, 5, 5, 0), 0, 0));
+        m_resultsPnl.setLayout(new java.awt.BorderLayout());
+        m_resultsPnl.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1), "Scan Results", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        m_resultsPnl.add(jScrollPane2, java.awt.BorderLayout.CENTER);
+        jScrollPane2.getViewport().add(m_resultsTbl);
+        m_buttonPnl.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 15, 5));
+        m_buttonPnl.add(m_doneBut);
+        m_buttonPnl.add(m_scanBut);
+        m_doneBut.setText("Done");
+        m_doneBut.setName("Done");
+        m_doneBut.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                closeDialog() ;
+            }
+        }) ;
+
+        jLabel1.setText("Key Constraint:");
+        m_keyText.setText("");
+        m_keyText.setMinimumSize(new java.awt.Dimension(130, 20));
+        m_keyText.setPreferredSize(new java.awt.Dimension(130, 20));
+        m_keyText.setMaximumSize(new java.awt.Dimension(130, 20));
+        m_keyText.setFont(new java.awt.Font("SansSerif", java.awt.Font.PLAIN, 14));
+        m_keyText.setSize(new java.awt.Dimension(130, 20));
+        jLabel2.setText("Cursor Type:");
+        m_cursorType.setMaximumSize(new java.awt.Dimension(32767, 20));
+        m_cursorType.setMinimumSize(new java.awt.Dimension(126, 20));
+        m_cursorType.setPreferredSize(new java.awt.Dimension(130, 20));
+        DefaultComboBoxModel l_comboModel = new DefaultComboBoxModel() ;
+        l_comboModel.addElement(DEFAULT_CURSOR) ;
+        l_comboModel.addElement(EQUALITY_CURSOR) ;
+        l_comboModel.addElement(GREATER_CURSOR) ;
+        l_comboModel.addElement(LESS_CURSOR) ;
+        l_comboModel.addElement(REGEX_CURSOR) ;
+        m_cursorType.setModel(l_comboModel) ;
+        m_cursorType.setMaximumRowCount(5);
+        m_scanBut.setText("Scan");
+        m_scanBut.setName("Scan");
+        m_scanBut.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                doScan(m_keyText.getText(),
+                    (String) m_cursorType.getSelectedItem()) ;
+            }
+        }) ;
+
+        doScan(null, DEFAULT_CURSOR) ;
+    }
+
+
+    private void closeDialog()
+    {
+        setVisible(false) ;
+        dispose() ;
+    }
+
+
+    public boolean doScan(String a_key, String a_cursorType)
+    {
+        if(a_key == null || a_key.trim().equals("")) {
+            a_key = null ;
+        }
+
+        if(a_key == null && a_cursorType != DEFAULT_CURSOR) {
+            JOptionPane.showMessageDialog(null, "Cannot use a " +
+                a_cursorType + " cursor type with a null key constraint.",
+                "Missing Key Constraint", JOptionPane.ERROR_MESSAGE) ;
+            return false ;
+        }
+
+        try {
+            Cursor l_cursor = null ;
+
+            if(a_cursorType == EQUALITY_CURSOR) {
+                l_cursor = m_index.getCursor(a_key) ;
+            } else if(a_cursorType == GREATER_CURSOR) {
+                l_cursor = m_index.getCursor(a_key, true) ;
+            } else if(a_cursorType == LESS_CURSOR) {
+                l_cursor = m_index.getCursor(a_key, false) ;
+            } else if(a_cursorType == REGEX_CURSOR) {
+                RE l_regex = StringTools.getRegex(a_key) ;
+                int l_starIndex = a_key.indexOf('*') ;
+
+                if(l_starIndex > 0) {
+                    String l_prefix = a_key.substring(0, l_starIndex) ;
+                    System.out.println("Regex prefix = " + l_prefix) ;
+                    l_cursor = m_index.getCursor(l_regex, l_prefix) ;
+                } else {
+                    l_cursor = m_index.getCursor(l_regex) ;
+                }
+            } else {
+                l_cursor = m_index.getCursor() ;
+            }
+
+            Object [] l_cols = new Object [2] ;
+            Object [] l_row = null ;
+            l_cols[0] = "Keys (Attribute Value)" ;
+            l_cols[1] = "Values (Entry Id)" ;
+            DefaultTableModel l_model = new DefaultTableModel(l_cols, 0) ;
+            int l_count = 0 ;
+            while(l_cursor.hasMore()) {
+                IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+                l_row = new Object [2] ;
+                l_row[0] = l_rec.getIndexKey() ;
+                l_row[1] = l_rec.getEntryId() ;
+                l_model.addRow(l_row) ;
+                l_count++ ;
+            } ;
+
+            m_resultsTbl.setModel(l_model) ;
+            m_resultsPnl.setBorder(
+                javax.swing.BorderFactory.createTitledBorder(
+                javax.swing.BorderFactory.createLineBorder(
+                new java.awt.Color(153, 153, 153), 1),
+                "Scan Results: " + l_count,
+                javax.swing.border.TitledBorder.LEADING,
+                javax.swing.border.TitledBorder.TOP,
+                new java.awt.Font("SansSerif", 0, 14),
+                new java.awt.Color(60, 60, 60))) ;
+
+            if(this.isVisible()) {
+                this.validate() ;
+            }
+        } catch(Exception e) {
+            String l_msg = ExceptionUtil.printStackTrace(e) ;
+            if(l_msg.length() > 1024) {
+                l_msg = l_msg.substring(0, 1024)
+                    + "\n. . . TRUNCATED . . ." ;
+            }
+            l_msg = "Error while scanning index "
+                + "on attribute " + m_index.getAttribute() + " using a "
+                + a_cursorType + " cursor type with a key constraint of '"
+                + a_key + "':\n" + l_msg ;
+            JTextArea l_area = new JTextArea() ;
+            l_area.setText(l_msg) ;
+            JOptionPane.showMessageDialog(null, l_area, "Index Scan Error",
+                JOptionPane.ERROR_MESSAGE) ;
+            return false ;
+        }
+
+        return true ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmBackendViewer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmBackendViewer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,74 @@
+/*
+ * $Id: JdbmBackendViewer.java,v 1.2 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+import javax.swing.UIManager ;
+import java.awt.Dimension ;
+import java.awt.Toolkit ;
+import java.io.File ;
+import javax.swing.JFileChooser ;
+
+import org.apache.log.Priority;
+import org.apache.log.Hierarchy;
+
+
+public class JdbmBackendViewer
+{
+    public JdbmBackendViewer()
+    {
+        BackendFrame frame = new BackendFrame() ;
+
+        String l_startPath = null ;
+        if(File.separatorChar == '/') {
+            l_startPath = "../projects" ;
+        } else {
+            l_startPath = "..\\projects" ;
+        }
+
+        final JFileChooser fc = new JFileChooser(l_startPath) ;
+        int returnVal = fc.showOpenDialog(frame);
+        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
+            File file = fc.getSelectedFile() ;
+            try {
+                frame.loadDatabase("ldapd.test.Harness", file.getParent()) ;
+            } catch(Exception ex) {
+                ex.printStackTrace() ;
+            }
+        } else {
+            // Write your code here what to do if user has canceled Open dialog
+        }
+
+        //Center the frame on screen
+        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension frameSize = frame.getSize();
+        frameSize.height = ((frameSize.height > screenSize.height)
+            ? screenSize.height : frameSize.height);
+        frameSize.width = ((frameSize.width > screenSize.width)
+            ? screenSize.width : frameSize.width);
+        frame.setLocation((screenSize.width - frameSize.width) / 2,
+            (screenSize.height - frameSize.height) / 2);
+        frame.setVisible(true);
+        System.out.println(frameSize) ;
+    }
+
+
+    public static void main(String[] argv) {
+        // set up system Look&Feel
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        }
+        catch (Exception e) {
+            System.out.println("Could not set look and feel to use " +
+                UIManager.getSystemLookAndFeelClassName() + ".") ;
+            //e.printStackTrace() ;
+        }
+        new JdbmBackendViewer ();
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmTableModel.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/JdbmTableModel.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,73 @@
+/*
+ * $Id: JdbmTableModel.java,v 1.2 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import java.util.ArrayList ;
+import javax.swing.table.AbstractTableModel ;
+
+
+public class JdbmTableModel
+    extends AbstractTableModel
+{
+    public static final String KEY_COL = "Keys" ;
+    public static final String VAL_COL = "Values" ;
+
+    private ArrayList m_keyList ;
+    private ArrayList m_valList ;
+
+
+    public JdbmTableModel(ArrayList a_keyList, ArrayList a_valList)
+    {
+        this.m_keyList = a_keyList ;
+        this.m_valList = a_valList ;
+    }
+
+
+    public String getColumnName(int a_col)
+    {
+        if(a_col == 0) {
+            return KEY_COL ;
+        } else if(a_col == 1) {
+            return VAL_COL ;
+        } else {
+            throw new RuntimeException("There can only be 2 columns at index "
+                + "0 and at 1") ;
+        }
+    }
+
+
+    public int getRowCount()
+    {
+        return m_keyList.size() ;
+    }
+
+
+    public int getColumnCount()
+    {
+        return 2 ;
+    }
+
+
+    public Object getValueAt(int a_row, int a_col)
+    {
+		if(a_row >= m_keyList.size()) {
+			return("NULL") ;
+		}
+
+        if(this.getColumnName(a_col).equals(KEY_COL)) {
+            return this.m_keyList.get(a_row) ;
+        } else if(this.getColumnName(a_col).equals(VAL_COL)) {
+            return this.m_valList.get(a_row) ;
+        } else {
+            throw new RuntimeException("You did not correctly set col names") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/MultiMapModel.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/MultiMapModel.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,91 @@
+/*
+ * $Id: MultiMapModel.java,v 1.2 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+
+import java.util.ArrayList ;
+import javax.swing.table.AbstractTableModel ;
+import org.apache.commons.collections.MultiMap;
+import java.util.Iterator;
+import java.util.Collection;
+
+
+public class MultiMapModel
+    extends AbstractTableModel
+{
+    public static final String KEY_COL = "Keys" ;
+    public static final String VAL_COL = "Values" ;
+
+    private final MultiMap m_map ;
+    private final ArrayList m_keys ;
+    private final int m_rowCount ;
+    private final ArrayList m_vals ;
+
+
+    public MultiMapModel(MultiMap a_map)
+    {
+        this.m_map = a_map ;
+        m_rowCount = m_map.values().size() ;
+        this.m_keys = new ArrayList(m_rowCount) ;
+        this.m_vals = new ArrayList(m_rowCount) ;
+
+        Iterator l_keyList = m_map.keySet().iterator() ;
+        while(l_keyList.hasNext()) {
+            String l_key = (String) l_keyList.next() ;
+            Iterator l_valList = ((Collection) m_map.get(l_key)).iterator() ;
+            while(l_valList.hasNext()) {
+                String l_val = l_valList.next().toString() ;
+                m_keys.add(l_key) ;
+                m_vals.add(l_val) ;
+            }
+        }
+    }
+
+
+    public String getColumnName(int a_col)
+    {
+        if(a_col == 0) {
+            return KEY_COL ;
+        } else if(a_col == 1) {
+            return VAL_COL ;
+        } else {
+            throw new RuntimeException("There can only be 2 columns at index "
+                + "0 and at 1") ;
+        }
+    }
+
+
+    public int getRowCount()
+    {
+        return m_rowCount ;
+    }
+
+
+    public int getColumnCount()
+    {
+        return 2 ;
+    }
+
+
+    public Object getValueAt(int a_row, int a_col)
+    {
+		if(a_row >= m_rowCount) {
+			return("NULL") ;
+		}
+
+        if(this.getColumnName(a_col).equals(KEY_COL)) {
+            return this.m_keys.get(a_row) ;
+        } else if(this.getColumnName(a_col).equals(VAL_COL)) {
+            return this.m_vals.get(a_row) ;
+        } else {
+            throw new RuntimeException("You did not correctly set col names") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/SearchResultDialog.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/SearchResultDialog.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,158 @@
+/*
+ * $Id: SearchResultDialog.java,v 1.2 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.gui ;
+
+import javax.swing.JDialog ;
+import java.awt.Frame ;
+import java.awt.event.WindowEvent ;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.JTextArea;
+import javax.swing.JButton;
+import javax.swing.tree.TreeModel;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.JTable;
+import javax.swing.table.TableModel;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.ListSelectionModel;
+import java.math.BigInteger;
+
+
+public class SearchResultDialog
+    extends JDialog implements ListSelectionListener
+{
+    private JPanel jPanel1 = new JPanel();
+    private JTree jTree1 = new JTree();
+    private JPanel jPanel2 = new JPanel();
+    private JPanel jPanel3 = new JPanel();
+    private JTextArea jTextArea1 = new JTextArea();
+    private JScrollPane jScrollPane1 = new JScrollPane();
+    private JButton jButton1 = new JButton();
+    private JPanel jPanel4 = new JPanel();
+    private JScrollPane jScrollPane2 = new JScrollPane();
+    private JTable m_resultsTbl = new JTable();
+
+    /** Creates new form JDialog */
+    public SearchResultDialog(Frame parent, boolean modal) {
+        super(parent, modal);
+        initGUI();
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     */
+    private void initGUI() {
+        addWindowListener(
+            new java.awt.event.WindowAdapter() {
+                public void windowClosing(java.awt.event.WindowEvent evt) {
+                    closeDialog(evt);
+                }
+            });
+        pack();
+        getContentPane().setLayout(new java.awt.GridBagLayout());
+        getContentPane().add(jPanel1,
+        new java.awt.GridBagConstraints(0, 0, 1, 1, 1.0, 0.1, java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(10, 5, 5, 5), 0, 0));
+        getContentPane().add(jPanel2,
+        new java.awt.GridBagConstraints(0, 1, 1, 1, 1.0, 0.4, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 5, 5), 0, 0));
+        getContentPane().add(jPanel3,
+        new java.awt.GridBagConstraints(0, 3, 1, 1, 1.0, 0.1, java.awt.GridBagConstraints.SOUTH, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(0, 0, 0, 0), 0, 0));
+        getContentPane().add(jPanel4,
+        new java.awt.GridBagConstraints(0, 2, 1, 1, 1.0, 0.4, java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH,
+        new java.awt.Insets(5, 5, 5, 5), 0, 0));
+        jPanel1.setLayout(new java.awt.BorderLayout(10, 10));
+        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1), "Specifications", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        jPanel1.add(jTextArea1, java.awt.BorderLayout.CENTER);
+        jScrollPane1.getViewport().add(jTree1);
+        jTree1.setBounds(new java.awt.Rectangle(238,142,82,80));
+        jTextArea1.setText("");
+        jTextArea1.setEditable(false);
+        setBounds(new java.awt.Rectangle(0, 0, 485, 434));
+        setTitle("Search Results");
+        jPanel2.setLayout(new java.awt.BorderLayout());
+        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1),
+        "Filter Expression Tree", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
+        jButton1.setText("Done");
+        jButton1.setActionCommand("Done");
+		jButton1.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent a_event) {
+                SearchResultDialog.this.setVisible(false) ;
+				SearchResultDialog.this.dispose() ;
+            }
+        }) ;
+        jButton1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+        jButton1.setAlignmentX(0.5f);
+        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+        jPanel3.setPreferredSize(new java.awt.Dimension(79, 41));
+        jPanel3.setMinimumSize(new java.awt.Dimension(79, 41));
+        jPanel3.setSize(new java.awt.Dimension(471,35));
+        jPanel3.setToolTipText("");
+        jPanel3.add(jButton1);
+        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(
+        new java.awt.Color(153, 153, 153), 1), "Search Results", javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
+        new java.awt.Font("SansSerif", 0, 14), new java.awt.Color(60, 60, 60)));
+        jPanel4.setLayout(new java.awt.BorderLayout());
+        jPanel4.add(jScrollPane2, java.awt.BorderLayout.CENTER);
+        jScrollPane2.getViewport().add(m_resultsTbl);
+        m_resultsTbl.setSize(new java.awt.Dimension(450,10));
+        m_resultsTbl.getSelectionModel().addListSelectionListener(this) ;
+    }
+
+
+    public void valueChanged(ListSelectionEvent an_event)
+    {
+        ListSelectionModel l_selectionModel = (ListSelectionModel) an_event.getSource() ;
+        int l_minIndex = l_selectionModel.getMinSelectionIndex() ;
+        int l_maxIndex = l_selectionModel.getMaxSelectionIndex() ;
+
+        for(int ii = l_minIndex ; ii <= l_maxIndex; ii++) {
+            if(l_selectionModel.isSelectedIndex(ii) && !an_event.getValueIsAdjusting()) {
+                BigInteger l_id = (BigInteger)
+                    m_resultsTbl.getModel().getValueAt(ii, 0) ;
+                ((BackendFrame) getParent()).selectTreeNode(l_id) ;
+            }
+        }
+    }
+
+
+    /** Closes the dialog */
+    private void closeDialog(WindowEvent evt) {
+        setVisible(false);
+        dispose();
+    }
+
+
+    public void setTreeModel(TreeModel a_model)
+    {
+        this.jTree1.setModel(a_model) ;
+    }
+
+
+    public void setFilter(String a_filter)
+    {
+        this.jTextArea1.setText(a_filter) ;
+    }
+
+
+    public void setTableModel(TableModel a_model)
+    {
+        m_resultsTbl.setModel(a_model) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/gui/ldapd.gif
==============================================================================
Binary file. No diff available.

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/BigIntegerComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/BigIntegerComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,47 @@
+/*
+ * $Id: BigIntegerComparator.java,v 1.4 2003/03/13 18:27:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+
+import java.math.BigInteger ;
+import org.apache.eve.backend.jdbm.table.TableComparator ;
+
+
+public class BigIntegerComparator extends TableComparator
+{
+    /**
+     * Version id for serialization.
+     */
+    final static long serialVersionUID = 1L ;
+
+
+    /**
+     * Compare two objects.
+     *
+     * @param obj1 First object
+     * @param obj2 Second object
+     * @return 1 if obj1 > obj2, 0 if obj1 == obj2, -1 if obj1 < obj2
+     */
+     public int compare( Object an_obj1, Object an_obj2 ) {
+        if (an_obj1 == null) {
+            throw new IllegalArgumentException("Argument 'an_obj1' is null") ;
+        }
+
+        if (an_obj2 == null) {
+            throw new IllegalArgumentException("Argument 'an_obj2' is null") ;
+        }
+
+        //System.out.println("BigIntegerComparator.compare(" + an_obj1 + ", "
+        //    + an_obj2 + ")") ;
+        BigInteger l_int1 = (BigInteger) an_obj1 ;
+        BigInteger l_int2 = (BigInteger) an_obj2 ;
+        return l_int1.compareTo(l_int2) ;
+     }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/Index.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/Index.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,99 @@
+/*
+ * $Id: Index.java,v 1.6 2003/03/13 18:27:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+import org.apache.regexp.RE ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException ;
+
+
+/**
+ * Doc me!
+ * @todo Doc me!
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.6 $
+ */
+public interface Index
+{
+    public String getAttribute() ;
+
+    public String getFilePath() ;
+
+    public int count()
+        throws BackendException, NamingException ;
+
+    public int count(Object an_attrVal)
+        throws BackendException, NamingException ;
+
+    public int count(Object an_attrVal, boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public BigInteger getForward(Object an_attrVal)
+        throws BackendException, NamingException ;
+
+    public Object getReverse(BigInteger a_id)
+        throws BackendException ;
+
+	public void add(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException ;
+
+	public void drop(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException ;
+
+
+    ///////////////////////
+    // Cursor Operations //
+    ///////////////////////
+
+    /*
+    public IndexCursor getReverseCursor()
+        throws BackendException, NamingException ;
+        */
+
+    public IndexCursor getReverseCursor(BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getCursor()
+        throws BackendException, NamingException ;
+
+    public IndexCursor getCursor(Object an_attrVal)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getCursor(Object an_attrVal, boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getCursor(RE a_regex)
+        throws BackendException, NamingException ;
+
+    public IndexCursor getCursor(RE a_regex, String a_prefix)
+        throws BackendException, NamingException ;
+
+    public boolean hasValue(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public boolean hasValue(Object an_attrVal, BigInteger a_id,
+        boolean isGreaterThan)
+        throws BackendException, NamingException ;
+
+    public boolean hasValue(RE a_regex, BigInteger a_id)
+        throws BackendException, NamingException ;
+
+    public void close()
+        throws BackendException ;
+
+    public void sync()
+        throws BackendException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,110 @@
+/*
+ * $Id: IndexComparator.java,v 1.4 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+
+import org.apache.eve.backend.jdbm.table.TupleComparator ;
+import org.apache.eve.backend.jdbm.table.TableComparator ;
+
+
+/**
+ * Doc me!
+ * @todo Doc me!
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public class IndexComparator
+    implements TupleComparator
+{
+    public static final StringComparator strComp =
+        new StringComparator() ;
+    public static final BigIntegerComparator intComp =
+        new BigIntegerComparator() ;
+
+    private final boolean isForwardMap ;
+    private final TableComparator m_keyComp ;
+
+
+    public IndexComparator(TableComparator a_keyComp, boolean isForwardMap)
+    {
+        m_keyComp = a_keyComp ;
+        this.isForwardMap = isForwardMap ;
+    }
+
+
+    /**
+     * Gets the comparator used to compare keys.  May be null in which
+     * case the compareKey method will throw an UnsupportedOperationException.
+     *
+     * @return the comparator for comparing keys.
+     */
+	public TableComparator getKeyComparator()
+    {
+        if(this.isForwardMap) {
+            return m_keyComp ;
+        }
+
+        return intComp ;
+    }
+
+
+    /**
+     * Gets the binary comparator used to compare valuess.  May be null in which
+     * case the compareValue method will throw an UnsupportedOperationException.
+     *
+     * @return the binary comparator for comparing values.
+     */
+	public TableComparator getValueComparator()
+    {
+        if(this.isForwardMap) {
+            return intComp ;
+        }
+
+        return m_keyComp ;
+    }
+
+
+    /**
+     * Compares key Object to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_key1 the first key to compare
+     * @param a_key2 the other key to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second byte array.
+     */
+    public int compareKey(Object a_key1, Object a_key2)
+    {
+        jdbm.helper.Comparator l_comparator =
+            (jdbm.helper.Comparator) getKeyComparator() ;
+        return l_comparator.compare(a_key1, a_key2) ;
+    }
+
+
+    /**
+     * Comparse value Objects to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_value1 the first value to compare
+     * @param a_value2 the other value to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second Object.
+     */
+    public int compareValue(Object a_value1, Object a_value2)
+    {
+        jdbm.helper.Comparator l_comparator =
+            (jdbm.helper.Comparator) getValueComparator() ;
+        return l_comparator.compare(a_value1, a_value2) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,106 @@
+/*
+ * $Id: IndexCursor.java,v 1.3 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException;
+import javax.naming.NamingException;
+import jdbm.helper.Tuple;
+import org.apache.regexp.RE;
+
+
+public class IndexCursor
+    extends Cursor
+{
+    private final RE m_re ;
+    private final IndexRecord m_tmp = new IndexRecord() ;
+    private final IndexRecord m_returned = new IndexRecord() ;
+    private final IndexRecord m_prefetched = new IndexRecord() ;
+    private final boolean swapKeyVal ;
+    private final Cursor m_cursor ;
+
+
+    IndexCursor(Cursor a_cursor)
+        throws BackendException, NamingException
+    {
+        this(a_cursor, false, null) ;
+    }
+
+
+    IndexCursor(Cursor a_cursor, boolean swapKeyVal)
+        throws BackendException, NamingException
+    {
+        this(a_cursor, swapKeyVal, null) ;
+    }
+
+
+    IndexCursor(Cursor a_cursor, boolean swapKeyVal, RE a_regex)
+        throws BackendException, NamingException
+    {
+        m_re = a_regex ;
+        m_cursor = a_cursor ;
+        this.swapKeyVal = swapKeyVal ;
+
+        if(a_cursor.isClosed()) {
+            super.close() ;
+            return ;
+        }
+
+        prefetch() ;
+    }
+
+
+    private void prefetch()
+        throws BackendException, NamingException
+    {
+        while(m_cursor.hasMore()) {
+            Tuple l_tuple = (Tuple) m_cursor.next() ;
+
+            if(swapKeyVal) {
+                m_tmp.setSwapped(l_tuple) ;
+            } else {
+                m_tmp.setTuple(l_tuple) ;
+            }
+
+            // If regex is null just transfer into prefetched from tmp record
+            // but if it is not then use it to match.  Successful match shorts
+            // while loop.
+            if(null == m_re || m_re.match((String) m_tmp.getIndexKey())) {
+                m_prefetched.setIndexKey(m_tmp.getIndexKey()) ;
+                m_prefetched.setEntryId(m_tmp.getEntryId()) ;
+                return ;
+            }
+        }
+
+        // If we got down here then m_cursor has been consumed without a match!
+        close() ;
+    }
+
+
+    protected Object advance()
+        throws BackendException, NamingException
+    {
+        m_returned.setEntryId(m_prefetched.getEntryId()) ;
+        m_returned.setIndexKey(m_prefetched.getIndexKey()) ;
+        prefetch() ;
+        return m_returned ;
+    }
+
+
+    protected boolean canAdvance()
+        throws BackendException, NamingException
+    {
+        return !isClosed() ;
+    }
+
+
+    protected void freeResources() {/*Does nothing*/}
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexRecord.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/IndexRecord.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,59 @@
+/*
+ * $Id: IndexRecord.java,v 1.3 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index;
+
+
+import jdbm.helper.Tuple ;
+import java.math.BigInteger ;
+
+
+public class IndexRecord
+{
+    private final Tuple m_tuple = new Tuple() ;
+
+
+    public void setTuple(Tuple a_tuple)
+    {
+        m_tuple.setKey(a_tuple.getKey()) ;
+        m_tuple.setValue(a_tuple.getValue()) ;
+    }
+
+
+    public void setSwapped(Tuple a_tuple)
+    {
+        m_tuple.setKey(a_tuple.getValue()) ;
+        m_tuple.setValue(a_tuple.getKey()) ;
+    }
+
+
+    public BigInteger getEntryId()
+    {
+        return (BigInteger) m_tuple.getValue() ;
+    }
+
+
+    public Object getIndexKey()
+    {
+        return m_tuple.getKey() ;
+    }
+
+
+    public void setEntryId(BigInteger a_id)
+    {
+        m_tuple.setValue(a_id) ;
+    }
+
+
+    public void setIndexKey(Object a_key)
+    {
+        m_tuple.setKey(a_key) ;
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/JdbmIndex.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/JdbmIndex.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,400 @@
+/*
+ * Id: JdbmIndex.java,v 1.10 2003/01/31 04:26:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+
+import java.io.IOException ;
+import java.io.File ;
+import java.math.BigInteger ;
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.backend.Cursor ;
+import org.apache.ldap.common.util.StringTools ;
+import org.apache.eve.schema.Normalizer ;
+import org.apache.ldap.common.NotImplementedException ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.table.JdbmTable ;
+import org.apache.eve.backend.jdbm.table.TableComparator ;
+
+import jdbm.recman.RecordManager ;
+
+import org.apache.regexp.RE ;
+import org.apache.commons.collections.LRUMap ;
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+
+
+/**
+ * Doc me!
+ * @todo Doc me!
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.12 $
+ */
+public class JdbmIndex
+    extends AbstractLogEnabled
+    implements Index
+{
+    public static final String FORWARD_BTREE = "_forward" ;
+    public static final String REVERSE_BTREE = "_reverse" ;
+
+    private final boolean isString ;
+    private final boolean isDecimal ;
+    private final boolean isInteger ;
+    private final String m_filePath ;
+    private final String m_attribute ;
+    private final Normalizer m_normalizer ;
+
+    private JdbmTable m_forward = null ;
+    private JdbmTable m_reverse = null ;
+    private RecordManager m_recMan = null ;
+    private LRUMap m_keyCache = null ;
+
+
+    public JdbmIndex(String a_attribute, Schema a_schema, String a_wkDirPath)
+        throws BackendException, NamingException
+    {
+        File l_file = new File(a_wkDirPath + File.separator + a_attribute) ;
+        m_filePath = l_file.getAbsolutePath() ;
+        m_attribute = a_attribute ;
+
+        TableComparator l_tableComp = null ;
+
+        if(a_attribute == Schema.DN_ATTR ||
+            a_attribute.equals(Schema.DN_ATTR)) {
+            final NameParser l_parser = a_schema.getNormalizingParser() ;
+            m_normalizer = new Normalizer() {
+                public String getEqualityMatch() {
+                    return "distinguishedNameMatch" ;
+                }
+                public String normalize(String a_str)
+                    throws NamingException
+                {
+                    return l_parser.parse(a_str).toString() ;
+                }
+            } ;
+            this.isDecimal = false ;
+            this.isString = true ;
+            this.isInteger = false ;
+            m_keyCache = new LRUMap(1000) ;
+            l_tableComp = IndexComparator.strComp ;
+        } else if(a_attribute == Schema.EXISTANCE_ATTR ||
+            a_attribute.equals(Schema.EXISTANCE_ATTR)) {
+            m_normalizer = new Normalizer() {
+                public String getEqualityMatch() {
+                    return "caseIgnoreMatch" ;
+                }
+                public String normalize(String a_str) {
+                    return StringTools.deepTrimToLower(a_str) ;
+                }
+            } ;
+            this.isDecimal = false ;
+            this.isString = true ;
+            this.isInteger = false ;
+            m_keyCache = new LRUMap(1000) ;
+            l_tableComp = IndexComparator.strComp ;
+        } else if(a_attribute == Schema.HIERARCHY_ATTR ||
+            a_attribute.equals(Schema.HIERARCHY_ATTR)) {
+            m_normalizer = new Normalizer() {
+                public String getEqualityMatch() {
+                    return "integerMatch" ;
+                }
+                public String normalize(String a_str) {
+                    return a_str ;
+                }
+            } ;
+            this.isDecimal = false ;
+            this.isString = false ;
+            this.isInteger = true ;
+            l_tableComp = IndexComparator.intComp ;
+        } else {
+            m_normalizer = a_schema.getNormalizer(m_attribute, true) ;
+            if(a_schema.isDecimal(m_attribute)) {
+                this.isDecimal = true ;
+                this.isInteger = false ;
+                this.isString = false ;
+    
+                // We do not have a plan for handling decimal values now!
+                throw new NotImplementedException() ;
+            } else if(a_schema.isNumeric(m_attribute)) {
+                this.isInteger = true ;
+                this.isDecimal = false ;
+                this.isString = false ;
+                l_tableComp = IndexComparator.intComp ;
+            } else if(a_schema.isBinary(m_attribute)) {
+                throw new IllegalArgumentException(
+                    "Cannot create an index on binary attribute: '"
+                    + m_attribute + "'") ;
+            } else {
+                this.isInteger = false ;
+                this.isDecimal = false ;
+                this.isString = true ;
+                l_tableComp = IndexComparator.strComp ;
+                m_keyCache = new LRUMap(1000) ;
+            }
+        }
+
+        try {
+            m_recMan = new RecordManager(m_filePath) ;
+            m_recMan.disableTransactions() ;
+        } catch(IOException e) {
+            throw new BackendException("Could not initialize the record "
+                + "manager:\n" + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        m_forward = new JdbmTable(m_attribute + FORWARD_BTREE,
+            true, m_recMan, new IndexComparator(l_tableComp, true)) ;
+        m_reverse = new JdbmTable(m_attribute + REVERSE_BTREE,
+            true, m_recMan, new IndexComparator(l_tableComp, false)) ;
+    }
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        super.enableLogging(a_logger) ;
+        m_forward.enableLogging(a_logger) ;
+        m_reverse.enableLogging(a_logger) ;
+    }
+
+
+    public String getAttribute()
+    {
+        return m_attribute ;
+    }
+
+
+    public String getFilePath()
+    {
+        return m_filePath ;
+    }
+
+
+    ////////////////////////
+    // Scan Count Methods //
+    ////////////////////////
+
+
+    public int count()
+        throws BackendException, NamingException
+    {
+        return m_forward.count() ;
+    }
+
+
+    public Object getCanonical(Object an_attrVal)
+        throws NamingException
+    {
+        if(this.isString) {
+            String l_canonical = (String) m_keyCache.get(an_attrVal) ;
+
+            if(null == l_canonical) {
+                l_canonical = m_normalizer.normalize((String) an_attrVal) ;
+
+                // Double map it so if we use an already normalized
+                // value we can get back the same normalized value.
+                // and not have to regenerate a second time.
+                m_keyCache.put(an_attrVal, l_canonical) ;
+                m_keyCache.put(l_canonical, l_canonical) ;
+            }
+
+            return l_canonical ;
+        }
+
+        return an_attrVal ;
+    }
+
+
+    public int count(Object an_attrVal)
+        throws BackendException, NamingException
+    {
+        return m_forward.count(getCanonical(an_attrVal)) ;
+    }
+
+
+    public int count(Object an_attrVal, boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+        return m_forward.count(getCanonical(an_attrVal), isGreaterThan) ;
+    }
+
+
+    /////////////////////////////////
+    // Forward and Reverse Lookups //
+    /////////////////////////////////
+
+
+    public BigInteger getForward(Object an_attrVal)
+        throws BackendException, NamingException
+    {
+        return (BigInteger) m_forward.get(getCanonical(an_attrVal)) ;
+    }
+
+
+    public Object getReverse(BigInteger a_id)
+        throws BackendException
+    {
+        return m_reverse.get(a_id) ;
+    }
+
+
+    //////////////////////
+    // Add/Drop Methods //
+    //////////////////////
+
+
+    public synchronized void add(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        m_forward.put(getCanonical(an_attrVal), a_id) ;
+        m_reverse.put(a_id, getCanonical(an_attrVal)) ;
+    }
+
+
+    public synchronized void drop(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        m_forward.remove(getCanonical(an_attrVal), a_id) ;
+        m_reverse.remove(a_id, getCanonical(an_attrVal)) ;
+    }
+
+
+    ///////////////////////
+    // Cursor Operations //
+    ///////////////////////
+
+
+    public IndexCursor getReverseCursor(BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor =
+            new IndexCursor(m_reverse.getCursor(a_id), true) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public IndexCursor getCursor()
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor = new IndexCursor(m_forward.getCursor()) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public IndexCursor getCursor(Object an_attrVal)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor =
+            new IndexCursor(m_forward.getCursor(getCanonical(an_attrVal))) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public IndexCursor getCursor(Object an_attrVal, boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor = new IndexCursor(
+            m_forward.getCursor(getCanonical(an_attrVal), isGreaterThan)) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public IndexCursor getCursor(RE a_regex)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor =
+            new IndexCursor(m_forward.getCursor(), false, a_regex) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public IndexCursor getCursor(RE a_regex, String a_prefix)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor = new IndexCursor(m_forward.
+            getCursor(getCanonical(a_prefix), true), false, a_regex) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    //////////////////////////////////////////////////
+    // Value Assertion (a.k.a Index Lookup) Methods //
+    //////////////////////////////////////////////////
+
+
+    public boolean hasValue(Object an_attrVal, BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        return m_forward.has(getCanonical(an_attrVal), a_id) ;
+    }
+
+
+    public boolean hasValue(Object an_attrVal, BigInteger a_id,
+        boolean isGreaterThan)
+        throws BackendException, NamingException
+    {
+        return m_forward.has(getCanonical(an_attrVal), a_id, isGreaterThan) ;
+    }
+
+
+    public boolean hasValue(RE a_regex, BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        IndexCursor l_cursor =
+            new IndexCursor(m_reverse.getCursor(a_id), true, a_regex) ;
+        l_cursor.enableLogging(getLogger()) ;
+
+        boolean hasValue = l_cursor.hasMore() ;
+        l_cursor.close() ;
+        return hasValue ;
+    }
+
+
+    /////////////////////////
+    // Maintenance Methods //
+    /////////////////////////
+
+
+    public synchronized void close()
+        throws BackendException
+    {
+        try {
+            m_forward.close() ;
+			m_reverse.close() ;
+            m_recMan.commit() ;
+            m_recMan.close() ;
+        } catch(IOException e) {
+            throw new BackendException("Encountered error while closing "
+                + "backend index file for attribute " + this.m_attribute) ;
+        }
+    }
+
+
+    public synchronized void sync()
+        throws BackendException
+    {
+        try {
+            m_recMan.commit() ;
+        } catch(IOException e) {
+            throw new BackendException("Encountered error while closing "
+                + "backend index file for attribute " + this.m_attribute) ;
+        }
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/StringComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/index/StringComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,46 @@
+/*
+ * $Id: StringComparator.java,v 1.2 2003/03/13 18:27:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.index ;
+
+
+import org.apache.eve.backend.jdbm.table.TableComparator ;
+
+
+/**
+ * A StringComparator that is both a java.util.Comparator and a
+ * jdbm.helper.Comparator.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class StringComparator extends TableComparator
+{
+    /**
+     * Version id for serialization.
+     */
+    final static long serialVersionUID = 1L ;
+
+
+    /**
+     * Compare two objects.
+     */
+     public int compare( Object a_obj1, Object a_obj2 ) {
+        if (null == a_obj1) {
+            throw new IllegalArgumentException("Argument 'a_obj1' is null") ;
+        }
+
+        if (null == a_obj2) {
+            throw new IllegalArgumentException("Argument 'a_obj2' is null") ;
+        }
+
+        return ((String) a_obj1).compareTo(a_obj2) ;
+     }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Assertion.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Assertion.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,28 @@
+/*
+ * $Id: Assertion.java,v 1.2 2003/03/13 18:27:28 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import javax.naming.NamingException ;
+import org.apache.eve.backend.BackendException ;
+
+
+public interface Assertion
+{
+    /**
+     * Checks to see if a candidate is valid by evaluating an assertion
+     * against the candidate.
+     * 
+     * @param a_candidate the candidate to assert
+     * @return true if the candidate is valid, false otherwise
+     */
+    boolean assertCandidate(Object a_candidate)
+        throws BackendException, NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DefaultOptimizer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DefaultOptimizer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,199 @@
+/*
+ * $Id: DefaultOptimizer.java,v 1.2 2003/03/13 18:27:28 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import java.util.ArrayList ;
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.backend.Backend ;
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.eve.backend.BackendException ;
+
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.ldap.common.filter.LeafNode ;
+import org.apache.ldap.common.filter.ScopeNode ;
+import org.apache.ldap.common.filter.SimpleNode ;
+import org.apache.ldap.common.filter.BranchNode ;
+import org.apache.ldap.common.filter.PresenceNode ;
+
+
+/**
+ *
+ */
+public class DefaultOptimizer
+    implements Optimizer
+{
+    public static final BigInteger MAX = BigInteger.valueOf(Integer.MAX_VALUE) ;
+
+    /**
+     * Annotates the expression tree to determine optimal evaluation order based
+     * on the scan count for indices that exist for each expression node.  If an
+     * index on the attribute does not exist an IndexNotFoundException will be
+     * thrown.
+     */
+    public void annotate(Database a_db, ExprNode a_node)
+        throws BackendException, NamingException
+    {
+        // Start off with the worst case unless scan count say otherwise.
+        BigInteger l_count = MAX ;
+
+        if ( a_node instanceof ScopeNode )
+        {
+            ScopeNode l_scopeNode = (ScopeNode) a_node ;
+
+            if(l_scopeNode.getScope() == Backend.BASE_SCOPE) {
+                l_count = BigInteger.ONE ;
+            } else if(l_scopeNode.getScope() == Backend.SINGLE_SCOPE) {
+                BigInteger l_id = a_db.getEntryId(l_scopeNode.getBaseDn()) ;
+                l_count = BigInteger.valueOf(a_db.getChildCount(l_id)) ;
+            } else if(l_scopeNode.getScope() == Backend.SUBTREE_SCOPE) {
+                l_count = BigInteger.valueOf(a_db.count()) ;
+            }
+        }
+
+            //////////////////////////////////////////////////////////
+            //           H A N D L E   L E A F   N O D E S          //
+            //////////////////////////////////////////////////////////
+
+        // Each assertion leaf node is on an attribute.  We ask the index on
+        // that attribute for the scan count representing all the candidates
+        // that would satisfy the assertion.
+        else if(a_node.isLeaf()) {
+            LeafNode l_leaf = (LeafNode) a_node ;
+            switch(l_leaf.getAssertionType()) {
+            case(LeafNode.APPROXIMATE):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute(),
+                    ((SimpleNode) l_leaf).getValue())) ;
+                break ;
+            case(LeafNode.EQUALITY):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute(),
+                    ((SimpleNode) l_leaf).getValue())) ;
+                break ;
+            case(LeafNode.EXTENSIBLE):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute())) ;
+                break ;
+            case(LeafNode.GREATEREQ):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute(),
+                    ((SimpleNode) l_leaf).getValue(), true)) ;
+                break ;
+            case(LeafNode.LESSEQ):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute(),
+                    ((SimpleNode) l_leaf).getValue(), false)) ;
+                break ;
+            case(LeafNode.PRESENCE):
+                PresenceNode l_presenceNode = (PresenceNode) a_node ;
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    Schema.EXISTANCE_ATTR,
+                    l_presenceNode.getAttribute())) ;
+                break ;
+            case(LeafNode.SUBSTRING):
+                l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                    l_leaf.getAttribute())) ;
+                break ;
+            default:
+                throw new IllegalArgumentException("Unrecognized leaf node") ;
+            }
+
+            //////////////////////////////////////////////////////////
+            //         H A N D L E   B R A N C H   N O D E S        //
+            //////////////////////////////////////////////////////////
+
+        } else {
+            ArrayList l_children = null ;
+            BranchNode l_node = (BranchNode) a_node ;
+
+            switch(l_node.getOperator()) {
+            case(BranchNode.AND):
+                //
+                // ANDs or Conjunctions take the count of the smallest child
+                // as their count.  This is the best that a conjunction can do
+                // and should be used rather than the worst case. Notice that
+                // we annotate the child node with a recursive call before
+                // accessing its count parameter.
+                //
+                l_count = BigInteger.valueOf(Integer.MAX_VALUE) ;
+                l_children = l_node.getChildren() ;
+                for(int ii = 0; ii < l_children.size(); ii++) {
+                    ExprNode l_child = (ExprNode) l_children.get(ii) ;
+                    annotate(a_db, l_child) ;
+                    l_count =((BigInteger) l_child.get("count")).min(l_count) ;
+                }
+                break ;
+            case(BranchNode.NOT):
+                //
+                // Negation counts are estimated in two ways.  First if the
+                // sole child of the negation is a leaf or simple assertion
+                // on an existing index then the count of the negation is set
+                // to the count of all records in the respective index table
+                // as a very rough estimate of the worst possible case.
+                //
+                // If the child is a brach node then the count of the negation
+                // node is set to the total count of entries in the master
+                // table. This tactic is used to get a rough estimate since it
+                // is very costly to estimate the count of a negation over
+                // a compound expression.
+                //
+                ExprNode l_onlyChild = (ExprNode) l_node.getChildren().get(0) ;
+                annotate(a_db, l_onlyChild) ;
+
+                if(l_onlyChild.isLeaf()) {
+                    LeafNode l_leaf = (LeafNode) l_onlyChild ;
+                    String l_attribute = l_leaf.getAttribute() ;
+
+                    if(l_leaf instanceof PresenceNode) {
+                        l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                            Schema.EXISTANCE_ATTR)) ;
+                    } else {
+                        l_count = BigInteger.valueOf(a_db.getIndexScanCount(
+                            l_attribute)) ;
+                    }
+                } else {
+                    l_count = BigInteger.valueOf(a_db.count()) ;
+                }
+
+                break ;
+            case(BranchNode.OR):
+                //
+                // Disjunctions (OR) are the union of candidates across all
+                // subexpressions for this reason we accumulate the counts of
+                // all the child nodes. Notice that we annotate the child node
+                // with a recursive call before accessing its count parameter.
+                //
+                l_children = l_node.getChildren() ;
+                BigInteger l_total = BigInteger.ZERO ;
+                for(int ii = 0; ii < l_children.size(); ii++) {
+                    ExprNode l_child = (ExprNode) l_children.get(ii) ;
+                    annotate(a_db, l_child) ;
+                    l_total = l_total.add((BigInteger) l_child.get("count")) ;
+                }
+
+                l_count = l_total ;
+                break ;
+            default:
+                throw new IllegalArgumentException("Unrecognized branch node") ;
+            }
+        }
+
+        // Protect against overflow when counting.
+        if(l_count.compareTo(BigInteger.ZERO) < 0) {
+            l_count = MAX ;
+        }
+
+        a_node.set("count", l_count) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DisjunctionCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/DisjunctionCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,195 @@
+/*
+ * $Id: DisjunctionCursor.java,v 1.5 2003/05/04 17:46:52 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.AtomicBackend ;
+import org.apache.eve.backend.BackendModule ;
+import org.apache.eve.protocol.ProtocolModule ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.index.IndexRecord;
+
+
+/**
+ * A Cursor of Cursors performing a union on all underlying Cursors resulting
+ * in the disjunction of expressions represented by the constituant child
+ * Cursors. This cursor prefetches underlying Cursor values so that it can
+ * comply with the defined Cursor semantics.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net"> Alex Karasulu </a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.5 $
+ */
+public class DisjunctionCursor
+    extends Cursor
+{
+    /** The underlying child cursors */
+    private final Cursor [] m_children ;
+    /** LUT used to avoid returning duplicates */
+    private final Map m_candidates = new HashMap() ;
+    /** Index of current cursor used */
+    private int m_index = 0 ;
+    /** Candidate to return */
+    private final IndexRecord m_candidate = new IndexRecord() ;
+    /** Prefetched record returned */
+    private final IndexRecord m_prefetched = new IndexRecord() ;
+
+
+    /**
+     * Creates a DisjunctionCursor over a set of child Cursors.  The returned
+     * result is the union of all underlying Cursors without duplicates.
+     *
+     * @param a_backend the owning backend instance
+     * @param a_children array of child Cursors
+     */
+    public DisjunctionCursor(Cursor [] a_children)
+        throws NamingException
+    {
+        m_children = a_children ;
+
+        // Close this cursor if their are no children.
+        if(a_children.length <= 0) {
+            close() ;
+            return ;
+        }
+
+
+        // Advance to the first cursor that has a candidate for us.
+        while(!m_children[m_index].hasMore()) {
+            m_index++ ;
+
+            // Close and return if we exhaust the cursors without finding a
+            // valid candidate to return.
+            if(m_index >= m_children.length) {
+                close() ;
+                return ;
+            }
+        }
+
+        // Grab the next candidate and add it's id to the LUT/hash of candidates
+        IndexRecord l_rec = (IndexRecord) m_children[m_index].next() ;
+        m_prefetched.setEntryId(l_rec.getEntryId()) ;
+        m_prefetched.setIndexKey(l_rec.getIndexKey()) ;
+        m_candidates.put(m_prefetched.getEntryId(), m_prefetched.getEntryId()) ;
+    }
+
+
+    /**
+     * Advances this Cursor one position.  Duplicates are not returned so if
+     * underlying cursors keep returning duplicates the child cursors will be
+     * advanced until a unique candidate is found or all child cursors are
+     * exhausted.
+     *
+     * @return a candidate element
+     */
+    public Object advance()
+        throws BackendException, NamingException
+    {
+        // Store the last prefetched candidate to return in m_candidate
+        m_candidate.setEntryId(m_prefetched.getEntryId()) ;
+        m_candidate.setIndexKey(m_prefetched.getIndexKey()) ;
+
+        do {
+            // Advance to a Cursor that has the next valid candidate for us.
+            while(!m_children[m_index].hasMore()) {
+				if(getLogger().isDebugEnabled()) {
+					getLogger().debug("" //ProtocolModule.getMessageKey()
+						+ " - DisjunctionCursor.advance(): child cursor "
+						+ m_children[m_index] + " at index "
+						+ m_index + " has been exhausted.") ;
+				}
+
+                m_index++ ;
+        
+                // Close and return existing prefetched candidate if we
+                // have exhausted the underlying Cursors without finding a
+                // valid candidate to return.
+                if(m_index >= m_children.length) {
+					if(getLogger().isDebugEnabled()) {
+						getLogger().debug("" //ProtocolModule.getMessageKey()
+							+ " - DisjunctionCursor.advance(): no more child "
+							+ "indices left they have all been exhausted. "
+							+ "Closing this cursor. Returning last prefetched "
+                            + "candidate value of " + m_candidate) ;
+					}
+
+                    close() ;
+                    return m_candidate ;
+                }
+            }
+
+            // Grab next candidate!
+            IndexRecord l_rec = (IndexRecord) m_children[m_index].next() ;
+            m_prefetched.setIndexKey(l_rec.getIndexKey()) ;
+            m_prefetched.setEntryId(l_rec.getEntryId()) ;
+
+			if(getLogger().isDebugEnabled()) {
+				getLogger().debug("" //ProtocolModule.getMessageKey()
+					+ " - DisjunctionCursor.advance(): got next prefetched "
+					+ "candidate value of " + m_prefetched.getEntryId()
+					+ " Did we see it before? "
+                    + m_candidates.containsKey(m_prefetched.getEntryId())) ;
+			}
+
+            // Break through do/while if the candidate is seen for the first
+            // time, meaning we have not returned it already.
+        } while(m_candidates.containsKey(m_prefetched.getEntryId())) ;
+
+		if(getLogger().isDebugEnabled()) {
+			getLogger().debug("" //ProtocolModule.getMessageKey()
+				+ " - DisjunctionCursor.advance(): got next valid candidate "
+				+ "with a value of " + m_prefetched.getEntryId()
+                + ". Returning last "
+                + "prefetched value of " + m_candidate.getEntryId()) ;
+		}
+
+        // Add candidate to LUT of encountered candidates.
+        m_candidates.put(m_candidate.getEntryId(), m_candidate.getEntryId()) ;
+
+        // Return the original prefetched value
+        return m_candidate ;
+    }
+
+
+    /**
+     * Tests if a prefetched value exists and a call to advance will hence
+     * succeed.
+     *
+     * @return true if a call to advance will succeed false otherwise.
+     */
+    public boolean canAdvance()
+        throws BackendException, NamingException
+    {
+        return !isClosed() ;
+    }
+
+
+    /**
+     * Closes all the underlying Cursors.
+     */
+    public void freeResources()
+    {
+        for(int ii = 0; ii < m_children.length; ii++) {
+            // Close all children but don't fail fast meaning don't stop
+            // closing all children if one fails to close for some reason.
+            try {
+                m_children[ii].close() ;
+            } catch(Throwable t) {
+                getLogger().warn("Could not close underlying cursor " +
+                    m_children[ii], t) ;
+            }
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Optimizer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/Optimizer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,32 @@
+/*
+ * $Id: Optimizer.java,v 1.2 2003/03/13 18:27:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import javax.naming.NamingException ;
+
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.eve.backend.BackendException ;
+
+
+/**
+ * An optimizer applies heuristics to determine best execution path to a search
+ * filter based on scan counts within database indices.  It annotates the nodes
+ * of an expression subtree by setting a "count" key in the node.  Its goal is
+ * to annotate nodes with counts to indicate which nodes to iterate over thereby
+ * minimizing the number cycles in a search.  The SearchEngine relies on these
+ * count markers to determine the appropriate path.
+ */
+public interface Optimizer
+{
+    public void annotate(Database a_db, ExprNode a_node)
+        throws BackendException, NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/PrefetchCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/PrefetchCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,185 @@
+/*
+ * $Id: PrefetchCursor.java,v 1.3 2003/03/13 18:27:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.ArrayList ;
+
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.eve.backend.jdbm.JdbmDatabase ;
+import org.apache.eve.protocol.ProtocolModule ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.search.Assertion ;
+import org.apache.eve.backend.jdbm.index.IndexRecord ;
+
+
+/**
+ * A LogicalCursor represents a Cursor over wither a AND/NOT/OR expression in a
+ * filter. This cursor prefetches underlying Cursor values so that it can comply
+ * with the defined Cursor semantics.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net"> Alex Karasulu </a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public class PrefetchCursor
+    extends Cursor
+{
+    /** The prefetched candidate */
+    private final IndexRecord m_prefetched = new IndexRecord() ;
+    /** The returned candidate */
+    private final IndexRecord m_candidate = new IndexRecord() ;
+    /** The iteration cursor */
+    private final Cursor m_cursor ;
+    /** LUT used to avoid returning duplicates */
+    private final Map m_candidates ;
+    private final Assertion m_assertion ;
+    private final boolean checkDups ;
+
+
+    /**
+     * Cursor over a conjunction expression.  All children except the candidate
+     * child to be used for iteration are provided as expressions. The child
+     * cursor is the basis for the iteration.
+     *
+     * @param a_backend the owning backend instance
+     * @param a_cursor underlying iteration cursor
+     * @param a_assertions array of assertions minus the assertion expression
+     * used to construct this cursor.
+     */
+    public PrefetchCursor(Cursor a_cursor, Assertion a_assertion)
+        throws BackendException, NamingException
+    {
+        m_cursor = a_cursor ;
+        m_candidates = null ;
+        m_assertion = a_assertion ;
+        checkDups = false ;
+        prefetch() ;
+    }
+
+
+    public PrefetchCursor(Cursor a_cursor,
+        Assertion a_assertion, boolean enableDupCheck)
+        throws BackendException, NamingException
+    {
+        m_cursor = a_cursor ;
+        m_candidates = new HashMap() ;
+        m_assertion = a_assertion ;
+        checkDups = true ;
+        prefetch() ;
+    }
+
+
+    /**
+     * Checks to see is a candidate is valid by evaluation all assertions
+     * against the candidate.  Any assertion failure short circuts tests
+     * returning false.  Success through all assertions returns true.
+     *
+     * @param a_candidate the candidate to assert
+     * @return true if the candidate is valid, false otherwise
+     * @throws ClassCastException if the candidate is not a BigInteger.
+     */
+    protected boolean assertCandidate(Object a_candidate)
+        throws BackendException, NamingException
+    {
+        return m_assertion.assertCandidate(a_candidate) ;
+    }
+
+
+    /**
+     * Advances this Cursor one position.  Underlying Cursor may be advanced
+     * several possitions while trying to find the next prefetched candidate to
+     * return.  If underlying Cursor elements are not valid meaning they do not
+     * pass assertions then they are rejected for return and the next item is
+     * tested.  If the underlying Cursor is consumed, then the last prefetched
+     * value is returned and this Cursor is closed.
+     *
+     * @return a valid candidate element that passed all assertions.
+     */
+    public Object advance()
+        throws BackendException, NamingException
+    {
+        m_candidate.setEntryId(m_prefetched.getEntryId()) ;
+        m_candidate.setIndexKey(m_prefetched.getIndexKey()) ;
+        prefetch() ;
+        return m_candidate ;
+    }
+
+
+    private void prefetch()
+        throws BackendException, NamingException
+    {
+        IndexRecord l_rec = null ;
+
+        // Scan underlying Cursor until we arrive at the next valid candidate
+        // if the cursor is exhuasted we clean up after completing the loop
+        while(m_cursor.hasMore()) {
+            l_rec = (IndexRecord) m_cursor.next() ;
+
+            // If value is valid then we set it as the next candidate to return
+            if(assertCandidate(l_rec)) {
+                // dup checking is on but candidate is not in already seen LUT
+                // so we need to set it as next to return and add it to the LUT
+                if(checkDups && !m_candidates.containsKey(l_rec.getEntryId())) {
+                    m_prefetched.setEntryId(l_rec.getEntryId()) ;
+                    m_prefetched.setIndexKey(l_rec.getIndexKey()) ;
+                    m_candidates.put(l_rec.getEntryId(), l_rec.getEntryId()) ;
+                    return ;
+                // dup checking is on and candidate has already been seen so we
+                // need to skip it.
+                } else if(checkDups &&
+                    m_candidates.containsKey(l_rec.getEntryId()))
+                {
+                    continue ;
+                }
+
+                m_prefetched.setEntryId(l_rec.getEntryId()) ;
+                m_prefetched.setIndexKey(l_rec.getIndexKey()) ;
+                return ;
+            }
+        }
+
+        // At this pt the underlying Cursor has been exhaused so we close up
+        // and set the prefetched value to null so canAdvance returns false.
+        close() ;
+    }
+
+
+    /**
+     * Tests if a prefetched value exists and a call to advance will hence
+     * succeed.
+     *
+     * @return true if a call to advance will succeed false otherwise.
+     */
+    public boolean canAdvance()
+        throws BackendException, NamingException
+    {
+        return !isClosed() ;
+    }
+
+
+    /**
+     * Closes the underlying Cursor.
+     */
+    public void freeResources()
+    {
+        try {
+            m_cursor.close() ;
+        } catch(NamingException e) {
+            getLogger().warn("Could not close conjunction cursor child", e) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/SearchEngine.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/search/SearchEngine.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,493 @@
+/*
+ * $Id: SearchEngine.java,v 1.5.4.1 2003/10/01 03:37:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.search ;
+
+
+import java.util.Iterator ;
+import java.util.ArrayList ;
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.Backend ;
+import org.apache.ldap.common.filter.ExprNode ;
+import org.apache.ldap.common.filter.LeafNode ;
+import org.apache.ldap.common.filter.ScopeNode ;
+import org.apache.ldap.common.filter.SimpleNode ;
+import org.apache.ldap.common.filter.BranchNode ;
+import org.apache.ldap.common.filter.PresenceNode ;
+import org.apache.ldap.common.filter.SubstringNode ;
+import org.apache.eve.backend.jdbm.Database ;
+import org.apache.ldap.common.NotImplementedException ;
+import org.apache.ldap.common.message.DerefAliasesEnum;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.backend.jdbm.index.Index ;
+import org.apache.eve.backend.jdbm.index.IndexRecord ;
+
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+
+import org.apache.regexp.RE ;
+import org.apache.regexp.RESyntaxException ;
+
+
+/**
+ * Given a search filter and a scope the search engine identifies valid
+ * candidate entries returning their ids.
+ */
+public class SearchEngine
+    extends AbstractLogEnabled
+{
+    private Optimizer m_optimizer = new DefaultOptimizer() ;
+
+
+	public Optimizer getOptimizer()
+    {
+        return m_optimizer ;
+    }
+
+
+    public ExprNode addScopeNode(ExprNode a_node, String a_baseDn, int a_scope)
+    {
+        ScopeNode l_scopeNode = new ScopeNode(
+            DerefAliasesEnum.NEVERDEREFALIASES, a_baseDn, a_scope) ;
+        BranchNode l_top = new BranchNode(BranchNode.AND) ;
+        l_top.getChildren().add(l_scopeNode) ;
+        l_top.getChildren().add(a_node) ;
+        return l_top ;
+    }
+
+
+    public Cursor search(Database a_db,
+        ExprNode a_filter,
+        String a_baseDn,
+        int a_scope)
+        throws BackendException, NamingException
+    {
+        Cursor l_cursor = null ;
+        ExprNode l_root = addScopeNode(a_filter, a_baseDn, a_scope) ;
+        m_optimizer.annotate(a_db, l_root) ;
+        l_cursor = buildSearchCursor(a_db, l_root) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    ///////////////////////////////////////////////////////////////
+    //     C U R S O R   B U I L D I N G   F U N C T I O N S     //
+    ///////////////////////////////////////////////////////////////
+
+
+    public Cursor buildSearchCursor(final Database a_db, final ExprNode a_node)
+        throws BackendException, NamingException
+    {
+        Cursor l_cursor = null ;
+
+        if ( a_node instanceof ScopeNode )
+        {
+            return buildScopeCursor( a_db, ( ScopeNode ) a_node ) ;
+        }
+
+        if(a_node.isLeaf()) {
+            LeafNode l_leaf = (LeafNode) a_node ;
+
+            switch(l_leaf.getAssertionType()) {
+            case(LeafNode.APPROXIMATE):
+                l_cursor = a_db.getIndexCursor(l_leaf.getAttribute(),
+                    ((SimpleNode)l_leaf).getValue()) ;
+                break ;
+            case(LeafNode.EQUALITY):
+                l_cursor = a_db.getIndexCursor(l_leaf.getAttribute(),
+                    ((SimpleNode)l_leaf).getValue()) ;
+                break ;
+            case(LeafNode.EXTENSIBLE):
+                // N O T   I M P L E M E N T E D   Y E T !
+                throw new NotImplementedException() ;
+                //break ;
+            case(LeafNode.GREATEREQ):
+                l_cursor = a_db.getIndexCursor(l_leaf.getAttribute(),
+                    ((SimpleNode)l_leaf).getValue(), true) ;
+                break ;
+            case(LeafNode.LESSEQ):
+                l_cursor = a_db.getIndexCursor(l_leaf.getAttribute(),
+                    ((SimpleNode)l_leaf).getValue(), false) ;
+                break ;
+            case(LeafNode.PRESENCE):
+                l_cursor = a_db.getIndexCursor(Schema.EXISTANCE_ATTR,
+                    l_leaf.getAttribute().toLowerCase()) ;
+                break ;
+            case(LeafNode.SUBSTRING):
+                l_cursor = buildSubstringCursor(a_db, (SubstringNode) l_leaf) ;
+                break ;
+            default:
+                throw new IllegalArgumentException("Unknown leaf assertion") ;
+            }
+        }
+        else if (a_node instanceof ScopeNode )
+        {
+            l_cursor = buildScopeCursor(a_db, (ScopeNode) a_node) ;
+        }
+        else
+        {
+            BranchNode l_branch = (BranchNode) a_node ;
+            switch(l_branch.getOperator()) {
+            case(BranchNode.AND):
+                l_cursor = buildConjunctionCursor(a_db, l_branch) ;
+                break ;
+            case(BranchNode.NOT):
+                l_cursor = buildNegationCursor(a_db, l_branch) ;
+                break ;
+            case(BranchNode.OR):
+                l_cursor = buildDisjunctionCursor(a_db, l_branch) ;
+                break ;
+            default:
+                throw new IllegalArgumentException("Unknown branch operator") ;
+            }
+        }
+
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    public Cursor buildScopeCursor(final Database a_db, final ScopeNode a_node)
+        throws BackendException, NamingException
+	{
+        switch(a_node.getScope()) {
+        case(Backend.BASE_SCOPE):
+            final BigInteger l_id = a_db.getEntryId(a_node.getBaseDn()) ;
+            final IndexRecord l_record =
+                new IndexRecord() ;
+            l_record.setEntryId(l_id) ;
+            l_record.setIndexKey(a_node.getBaseDn()) ;
+
+            return new Cursor() {
+                public Object advance()
+                    throws NamingException
+                { super.close() ; return l_record ; }
+                public void freeResources() { }
+                public boolean canAdvance()
+                { return(!super.isClosed()) ; }
+            } ;
+        case(Backend.SINGLE_SCOPE):
+            return a_db.getChildren(a_db.getEntryId(a_node.getBaseDn())) ;
+        case(Backend.SUBTREE_SCOPE):
+            Assertion l_assertion = new Assertion()
+            {
+                public boolean assertCandidate(Object a_candidate)
+                    throws BackendException
+                {
+                    IndexRecord l_rec = (IndexRecord) a_candidate ;
+                    String l_dn = a_db.getEntryDn(l_rec.getEntryId()) ;
+                    return l_dn.endsWith(a_node.getBaseDn()) ;
+                }
+            } ;
+
+            // Gets a cursor over all elements
+            Cursor l_cursor = a_db.getIndexCursor(Schema.DN_ATTR) ;
+            return new PrefetchCursor(l_cursor, l_assertion) ;
+        default:
+            throw new BackendException("Unrecognized search scope!") ;
+        }
+    }
+
+
+    public Cursor buildSubstringCursor(final Database a_db,
+        final SubstringNode a_node)
+        throws BackendException, NamingException
+	{
+        Cursor l_cursor = null ;
+        RE l_regex = null ;
+
+        try {
+            l_regex = a_node.getRegex() ;
+        } catch(RESyntaxException e) {
+            throw new BackendException("SubstringNode '" + a_node + "' had "
+                + "encountered syntax exception: " + e.getMessage(), e) ;
+        }
+
+        if(a_node.getInitial() != null) {
+	        l_cursor = a_db.getIndexCursor(a_node.getAttribute(), l_regex,
+                a_node.getInitial()) ;
+	    } else {
+            l_cursor = a_db.getIndexCursor(a_node.getAttribute(), l_regex) ;
+        }
+
+        return l_cursor ;
+    }
+
+
+    /**
+     * Method involved in chain recursion while constructing the search cursor
+     * used to handle the Disjunction expression case.
+     */
+    public Cursor buildDisjunctionCursor(final Database a_db,
+        final BranchNode a_node)
+        throws BackendException, NamingException
+    {
+        Cursor l_cursor = null ;
+        ArrayList l_list = a_node.getChildren() ;
+        Cursor [] l_childCursors = new Cursor [l_list.size()] ;
+
+        // Recursively create Cursors for each of the child expression nodes.
+        for(int ii = 0 ; ii < l_childCursors.length; ii++) {
+            l_childCursors[ii] =
+                buildSearchCursor(a_db, (ExprNode) l_list.get(ii)) ;
+        }
+
+        // Create the Cursor enable logging on it and return.
+        l_cursor = new DisjunctionCursor(l_childCursors) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    /**
+     * Method involved in chain recursion while constructing the search cursor
+     * used to handle the Negation expression case.
+     */
+    public Cursor buildNegationCursor(final Database a_db,
+        final BranchNode a_node)
+        throws BackendException, NamingException
+    {
+        Cursor l_childCursor = null ;
+        Cursor l_cursor = null ;
+        final ExprNode l_childNode =
+            (ExprNode) a_node.getChildren().get(0) ;
+
+        // Iterates over entire set of index values.
+        if(l_childNode.isLeaf()) {
+            LeafNode l_child = (LeafNode) l_childNode ;
+            l_childCursor = a_db.getIndexCursor(l_child.getAttribute()) ;
+        } else { // Iterates over the entire set of entries.
+            l_childCursor = a_db.getIndexCursor(Schema.DN_ATTR) ;
+        }
+
+        l_childCursor.enableLogging(getLogger()) ;
+
+        Assertion l_assertion = new Assertion()
+        {
+            public boolean assertCandidate(Object a_candidate)
+                throws BackendException, NamingException
+            {
+                IndexRecord l_rec = (IndexRecord) a_candidate ;
+                // NOTICE THE ! HERE
+                // The candidate is valid if it does not pass assertion. A
+                // candidate that passes assertion is therefore invalid.
+                return !assertExpression(a_db, l_childNode, l_rec.getEntryId()) ;
+            }
+        } ;
+        l_cursor = new PrefetchCursor(l_childCursor, l_assertion, true) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    /**
+     * Method involved in chain recursion while constructing the search cursor
+     * used to handle the Conjunction expression case.
+     */
+    public Cursor buildConjunctionCursor(final Database a_db,
+        final BranchNode a_node)
+        throws BackendException, NamingException
+    {
+        int l_minIndex = 0 ;
+        int l_minValue = Integer.MAX_VALUE ;
+        int l_value = Integer.MAX_VALUE ;
+        ExprNode l_node = null ;
+        Cursor l_cursor = null ;
+
+        // We scan the child nodes of a branch node searching for the child
+        // expression node with the smallest scan count.  This is the child
+        // we will use for iteration by creating a cursor over its expression.
+        final ArrayList l_list = a_node.getChildren() ;
+        for(int ii = 0 ; ii < l_list.size(); ii++) {
+            l_node = (ExprNode) l_list.get(ii) ;
+            l_value = ((BigInteger) l_node.get("count")).intValue() ;
+            l_minValue = Math.min(l_minValue, l_value) ;
+
+            if(l_minValue == l_value) {
+                l_minIndex = ii ;
+            }
+        }
+
+        // Once found we construct the child cursor and the conjunction cursor.
+        final ExprNode l_cursorNode = (ExprNode) l_list.get(l_minIndex) ;
+
+        Assertion l_assertion = new Assertion()
+        {
+            public boolean assertCandidate(Object a_candidate)
+                throws BackendException, NamingException
+            {
+                IndexRecord l_rec = (IndexRecord) a_candidate ;
+
+                for(int ii = 0 ; ii < l_list.size(); ii++) {
+                    ExprNode l_child = (ExprNode) l_list.get(ii) ;
+
+                    if(l_child == l_cursorNode) {
+                        continue ;
+                    } else if(!assertExpression(a_db, l_child,
+                        l_rec.getEntryId())) {
+                        return false ;
+                    }
+                }
+
+                return true ;
+            }
+        } ;
+
+        Cursor l_childCursor = buildSearchCursor(a_db, l_cursorNode) ;
+        l_cursor = new PrefetchCursor(l_childCursor, l_assertion) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    //   E X P R E S S I O N   A S S E R T I O N   F U N C T I O N S   //
+    /////////////////////////////////////////////////////////////////////
+
+
+    public boolean assertExpression(final Database a_db, final ExprNode a_node,
+        final BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        if (a_node instanceof ScopeNode)
+        {
+            return assertScope( a_db, (ScopeNode) a_node, a_id ) ;
+        }
+        if(a_node.isLeaf()) {
+            return assertLeaf(a_db, (LeafNode) a_node, a_id) ;
+        }
+
+        return assertBranch(a_db, (BranchNode) a_node, a_id) ;
+    }
+
+
+    public boolean assertBranch(final Database a_db, final BranchNode a_node,
+        final BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        switch(a_node.getOperator()) {
+        case(BranchNode.OR):
+            Iterator l_children = a_node.getChildren().iterator() ;
+            while(l_children.hasNext()) {
+                ExprNode l_child = (ExprNode) l_children.next() ;
+                if(assertExpression(a_db, l_child, a_id)) {
+                    return true ;
+                }
+            }
+
+            return false ;
+        case(BranchNode.AND):
+            l_children = a_node.getChildren().iterator() ;
+            while(l_children.hasNext()) {
+                ExprNode l_child = (ExprNode) l_children.next() ;
+                if(!assertExpression(a_db, l_child, a_id)) {
+                    return false ;
+                }
+            }
+
+            return true ;
+        case(BranchNode.NOT):
+            ArrayList l_childArray = a_node.getChildren() ;
+            if(l_childArray.size() > 0) {
+                return !assertExpression(a_db,
+                    (ExprNode) l_childArray.get(0), a_id) ;
+            }
+
+            throw new BackendException("Negation has no child: " + a_node) ;
+        default:
+            throw new BackendException("Unrecognized branch node operator: "
+                + a_node.getOperator()) ;
+        }
+    }
+
+
+    public boolean assertLeaf(final Database a_db, final LeafNode a_node,
+        final BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        switch(a_node.getAssertionType()) {
+        case(LeafNode.APPROXIMATE):
+            return a_db.assertIndexValue(((SimpleNode) a_node).getAttribute(),
+                ((SimpleNode) a_node).getValue(), a_id) ;
+        case(LeafNode.EQUALITY):
+            return a_db.assertIndexValue(((SimpleNode) a_node).getAttribute(),
+                ((SimpleNode) a_node).getValue(), a_id) ;
+        case(LeafNode.EXTENSIBLE):
+            throw new NotImplementedException() ;
+        case(LeafNode.GREATEREQ):
+            return a_db.assertIndexValue(((SimpleNode) a_node).getAttribute(),
+                ((SimpleNode) a_node).getValue(), a_id, true) ;
+        case(LeafNode.LESSEQ):
+            return a_db.assertIndexValue(((SimpleNode) a_node).getAttribute(),
+                ((SimpleNode) a_node).getValue(), a_id, false) ;
+        case(LeafNode.PRESENCE):
+            return a_db.assertIndexValue(Schema.EXISTANCE_ATTR,
+                ((PresenceNode) a_node).getAttribute().toLowerCase(), a_id) ;
+        case(LeafNode.SUBSTRING):
+            return assertSubstring(a_db, (SubstringNode) a_node, a_id) ;
+        default:
+            throw new BackendException("Unrecognized leaf node type: "
+                + a_node.getAssertionType()) ;
+        }
+    }
+
+
+    public boolean assertScope(final Database a_db, final ScopeNode a_node,
+        final BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        String l_dn = a_db.getEntryDn(a_id) ;
+
+        switch(a_node.getScope()) {
+        case(Backend.BASE_SCOPE):
+            return l_dn.equals(a_node.getBaseDn()) ;
+        case(Backend.SINGLE_SCOPE):
+            Object l_key = a_db.getEntryId(a_node.getBaseDn()) ;
+            return a_db.assertIndexValue(Schema.HIERARCHY_ATTR, l_key, a_id) ;
+        case(Backend.SUBTREE_SCOPE):
+            return l_dn.endsWith(a_node.getBaseDn()) ;
+        default:
+            throw new BackendException("Unrecognized search scope!") ;
+        }
+    }
+
+
+    public boolean assertSubstring(final Database a_db,
+        final SubstringNode a_node,
+        final BigInteger a_id)
+        throws BackendException, NamingException
+    {
+        RE l_regex = null ;
+        Index l_index = a_db.getIndex(a_node.getAttribute()) ;
+        Cursor l_cursor = l_index.getReverseCursor(a_id) ;
+
+        try {
+            l_regex = a_node.getRegex() ;
+        } catch(RESyntaxException e) {
+            throw new BackendException("SubstringNode '" + a_node + "' had "
+                + "encountered syntax exception: " + e.getMessage(), e) ;
+        }
+
+        while(l_cursor.hasMore()) {
+            IndexRecord l_rec = (IndexRecord) l_cursor.next() ;
+            if(l_regex.match((String) l_rec.getIndexKey())) {
+                l_cursor.close() ;
+                return true ;
+            }
+        }
+
+        return false ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/DupsCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/DupsCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,111 @@
+/*
+ * $Id: DupsCursor.java,v 1.3 2003/03/13 18:27:30 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import java.util.TreeSet ;
+import java.util.Iterator ;
+import java.util.ArrayList ;
+import java.util.Collections ;
+
+import javax.naming.NamingException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException ;
+
+import jdbm.helper.Tuple ;
+
+
+/**
+ * Cursor that iterates over duplicate values nested into a value using a
+ * TreeSet.
+ *
+ * @warning The Tuple returned by this Cursor is always the same instance object
+ * returned every time. It is reused to for the sake of efficency rather than
+ * creating a new tuple for each advance() call.
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public class DupsCursor
+    extends Cursor
+{
+    private final Tuple m_returned = new Tuple() ;
+    private final Tuple m_prefetched = new Tuple() ;
+    private final NoDupsCursor m_cursor ;
+
+    private Iterator m_iterator ;
+    private Tuple m_duplicates ;
+
+
+    DupsCursor(NoDupsCursor a_cursor)
+        throws BackendException
+    {
+        m_cursor = a_cursor ;
+
+        try {
+            // Protect against closed cursors
+            if(m_cursor.isClosed()) {
+                close() ;
+                return ;
+            }
+    
+            prefetch() ;
+        } catch(NamingException e) { /* NEVER THROWN */ }
+    }
+
+
+    private void prefetch()
+        throws BackendException, NamingException
+    {
+        while(null == m_iterator || !m_iterator.hasNext()) {
+            if(m_cursor.hasMoreElements()) {
+                m_duplicates = (Tuple) m_cursor.next() ;
+                TreeSet l_set = (TreeSet) m_duplicates.getValue() ;
+
+                if(m_cursor.doAscendingScan()) {
+                    m_iterator = l_set.iterator() ;
+                } else {
+                    ArrayList l_list = new ArrayList(l_set.size()) ;
+                    l_list.addAll(l_set) ;
+                    Collections.reverse(l_list) ;
+                    m_iterator = l_list.iterator() ;
+                }
+            } else {
+                close() ;
+                return ;
+            }
+        }
+
+        m_prefetched.setKey(m_duplicates.getKey()) ;
+        m_prefetched.setValue(m_iterator.next()) ;
+    }
+
+
+    public Object advance()
+        throws BackendException, NamingException
+    {
+        m_returned.setKey(m_prefetched.getKey()) ;
+        m_returned.setValue(m_prefetched.getValue()) ;
+
+        prefetch() ;
+
+        return m_returned ;
+    }
+
+
+    public boolean canAdvance()
+    {
+        return !isClosed() ;
+    }
+
+
+    public void freeResources() { /* Does nothing! */ }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/JdbmTable.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/JdbmTable.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,989 @@
+/*
+ * $Id: JdbmTable.java,v 1.13 2003/03/13 18:27:31 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import java.util.TreeSet ;
+import java.util.SortedSet ;
+import java.util.ArrayList ;
+import java.util.Collections ;
+import java.io.IOException ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.EmptyCursor ;
+import org.apache.eve.backend.SingletonCursor ;
+import org.apache.eve.backend.BackendException ;
+
+import jdbm.helper.MRU ;
+import jdbm.btree.BTree ;
+import jdbm.helper.Tuple ;
+import jdbm.helper.Comparator ;
+import jdbm.helper.ObjectCache ;
+import jdbm.helper.TupleBrowser ;
+import jdbm.recman.RecordManager ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+
+
+/**
+ * A jdbm Btree wrapper that enables duplicate sorted keys using collections.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.13 $
+ */
+public class JdbmTable
+    extends AbstractLogEnabled implements Table
+{
+    private static final int CACHE_SIZE = 1000 ;
+    private static final String SZSUFFIX = "_btree_sz" ;
+
+    private final String m_name ;
+    private final RecordManager m_recMan ;
+    private final boolean allowsDuplicates ;
+    private final TupleComparator m_comparator ;
+
+    private int m_count = 0 ;
+    private BTree m_bt ;
+    private TupleRenderer m_renderer ;
+
+
+    //////////////////
+    // Constructors //
+    //////////////////
+
+    /**
+     * A jdbm Btree backed table.
+     */
+    public JdbmTable(String a_name, boolean allowsDuplicates,
+        RecordManager a_manager, TupleComparator a_comparator)
+        throws BackendException
+    {
+        m_name = a_name ;
+        m_recMan = a_manager ;
+        m_comparator = a_comparator ;
+        this.allowsDuplicates = allowsDuplicates ;
+
+        try {
+            ObjectCache m_cache =
+                new ObjectCache(m_recMan, new MRU(CACHE_SIZE)) ;
+    
+            long l_recId = m_recMan.getNamedObject(m_name) ;
+            if(l_recId != 0) {
+                m_bt = BTree.load(m_recMan, m_cache, l_recId) ;
+                l_recId = m_recMan.getNamedObject(m_name + SZSUFFIX) ;
+                m_count = ((Integer) m_recMan.fetchObject(l_recId)).intValue() ;
+            } else {
+                m_bt = new BTree(m_recMan, m_cache,
+                    (jdbm.helper.Comparator) a_comparator.getKeyComparator()) ;
+                l_recId = m_bt.getRecid() ;
+                m_recMan.setNamedObject(m_name, l_recId) ;
+
+				l_recId = m_recMan.insert(new Integer(0)) ;
+				m_recMan.setNamedObject(m_name + SZSUFFIX, l_recId) ;
+            }
+        } catch(Throwable e) {
+            throw new BackendException("Failed to load/create Btree:\n"
+                + ExceptionUtil.printStackTrace(e), e) ;
+        }
+    }
+
+
+    /**
+     * A jdbm Btree backed table.
+     */
+    public JdbmTable(String a_name, RecordManager a_manager,
+        TableComparator a_keyComparator)
+        throws BackendException
+    {
+        this(a_name, false, a_manager, new KeyOnlyComparator(a_keyComparator)) ;
+    }
+
+
+    /**
+     * Gets the comparator used by this Table: may be null if this Table was
+     * not initialized with one.
+     *
+     * @return the final comparator instance or null if this Table was not
+     * created with one.
+     */
+    public TupleComparator getComparator()
+    {
+        return m_comparator ;
+    }
+
+
+    /**
+     * Checks to see if this Table has enabled the use of duplicate keys.
+     *
+     * @return true if duplicate keys are enabled, false otherwise.
+     */
+	public boolean isDupsEnabled()
+    {
+        return allowsDuplicates;
+    }
+
+
+    /**
+     * Gets the name of this Table.
+     *
+     * @return the name
+     */
+    public String getName()
+    {
+        return m_name ;
+    }
+
+
+    /**
+     * Gets the data renderer used by this Table to display or log records keys
+     * and values.
+     *
+     * @return the renderer used
+     */
+    public TupleRenderer getRenderer()
+    {
+        return m_renderer ;
+    }
+
+
+    /**
+     * Sets the data renderer to by used by this Table to display or log record
+     * keys and values.
+     *
+     * @param a_renderer the DataRenderer instance to used as the renderer.
+     */
+    public void setRenderer(TupleRenderer a_renderer)
+    {
+        m_renderer = a_renderer ;
+    }
+
+
+    /**
+     * Checks to see if this Table has enabled sorting on the values of
+     * duplicate keys.  This will always return true but may change after
+     * this release.
+     *
+     * @return true if duplicate key values are sorted, false otherwise.
+     */
+	public boolean isSortedDupsEnabled()
+    {
+        // If duplicates are enabled than duplicates will be maintained in
+        // sorted order.
+        return allowsDuplicates ;
+    }
+
+
+    /**
+     * This operation is not supported by this implementation.  Will always
+     * throw a UnsupportedOperationException.
+     *
+     * @param a_key the Object key to count.
+     * @param isGreaterThan boolean set to true to count for greater than and
+     * equal to record keys, or false for less than or equal to keys.
+     * @return the number of keys greater or less than a_key.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count(Object a_key, boolean isGreaterThan)
+        throws BackendException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Gets the count of the number of records in this Table with a specific
+     * key: returns the number of duplicates for a key.
+     *
+     * @param a_key the Object key to count.
+     * @return the number of duplicate records for a key.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count(Object a_key)
+        throws BackendException
+    {
+        if(!allowsDuplicates) {
+            getLogger().warn("JdbmTable.count(Object):"
+                + " Should not be calling this method for tables that"
+                + " do not support duplicates.") ;
+
+            if(null == getRaw(a_key)) {
+                return 0 ;
+            } else {
+                return 1 ;
+            }
+        }
+
+        TreeSet l_set = (TreeSet) getRaw(a_key) ;
+
+        if(l_set != null) {
+            return l_set.size() ;
+        }
+
+        return 0 ;
+    }
+
+
+    /**
+     *
+     * @return the number of keys
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count()
+        throws BackendException
+    {
+        return m_count ;
+    }
+
+
+    /**
+     * Gets the value of a record by key if the key exists.  If this Table
+     * allows duplicate keys then the first key will be returned.  If this
+     * Table is also a Btree that first key will be the smallest key in the
+     * Table as specificed by this Table's comparator or the default berkeley
+     * bytewise lexical comparator.
+     *
+     * @param a_key the key of the record
+     * @return the value of the record with a_key if a_key exists or null if
+     * no such record exists.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public Object get(Object a_key)
+        throws BackendException
+    {
+        if(allowsDuplicates) {
+            TreeSet l_set = (TreeSet) getRaw(a_key) ;
+            if(null == l_set || l_set.size() == 0) {
+                return null ;
+            } else {
+                return l_set.first() ;
+            }
+        }
+
+        return getRaw(a_key) ;
+    }
+
+
+    /**
+     * Checks to see if this table has a record with a key equal to the
+     * argument key with a value greater/less than or equal to the value
+     * argument provided.  The key argument <strong>MUST</strong> exist for
+     * this call to return true and the underlying Db must be a Btree that
+     * allows for sorted duplicate values.  The entire basis to this method
+     * depends on the fact that duplicate key values are sorted according to
+     * a valid value comparator function.
+     *
+     * @param a_key the key Object
+     * @param a_val the value Object to compare values to
+     * @param isGreaterThan boolean for greater than or less then comparison
+     * @return true if a record with a key greater/less than the key argument
+     * exists, false otherwise
+     * @throws BackendException if there is a failure to read the underlying Db
+     * or if the underlying Db does not allow sorted duplicate values.
+     */
+	public boolean has(Object a_key, Object a_val, boolean isGreaterThan)
+        throws BackendException
+    {
+        if(!allowsDuplicates) {
+            getLogger().warn("JdbmTable.has(Object, Object, boolean):"
+                + " Should not be calling this method for tables that"
+                + " do not support duplicates.") ;
+
+            Object l_val = getRaw(a_key) ;
+
+            // key does not exist so return nothing
+            if(null == l_val) {
+				return false ;
+            }
+            // l_val == a_val return tuple
+            else if(a_val.equals(l_val)) {
+                return true ;
+            }
+			// l_val >= a_val and test is for greater then return tuple
+            else if(m_comparator.compareValue(l_val, a_val) >= 1 &&
+                isGreaterThan)
+            {
+				return true ;
+            }
+			// l_val <= a_val and test is for lesser then return tuple
+            else if(m_comparator.compareValue(l_val, a_val) <= 1 &&
+                !isGreaterThan)
+            {
+				return true ;
+        	}
+            // key's value does not equal a_val and conditions not satisfied.
+            else {
+                return false ;
+            }
+        }
+
+        TreeSet l_set = (TreeSet) getRaw(a_key) ;
+        if(null == l_set || l_set.size() == 0) {
+            return false ;
+        }
+
+        SortedSet l_subset = null ;
+        if(isGreaterThan) {
+            l_subset = l_set.tailSet(a_val) ;
+        } else {
+            l_subset = l_set.headSet(a_val) ;
+        }
+
+        if(l_subset.size() > 0 || l_set.contains(a_val)) {
+            return true ;
+        }
+
+        return false ;
+    }
+
+
+    /**
+     * Checks to see if this table has a record with a key greater/less than or
+     * equal to the key argument.  The key argument need not exist for this
+     * call to return true.
+     *
+     * @param a_key the key Object to compare keys to
+     * @param isGreaterThan boolean for greater than or less then comparison
+     * @return true if a record with a key greater/less than the key argument
+     * exists, false otherwise
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+	public boolean has(Object a_key, boolean isGreaterThan)
+        throws BackendException
+    {
+        try {
+            // See if we can find the border between keys greater than and less
+            // than in the set of keys.  This will be the spot we search from.
+            Tuple l_tuple = m_bt.findGreaterOrEqual(a_key) ;
+    
+            // Test for equality first since it satisfies both greater/less than
+            if(null != l_tuple &&
+                m_comparator.compareKey(l_tuple.getKey(), a_key) == 0)
+            {
+                return true ;
+            }
+    
+            // Greater searches are easy and quick thanks to findGreaterOrEqual
+            if(isGreaterThan) {
+                // A null return above means there were no equal or greater keys
+                if(null == l_tuple) {
+                    return false ;
+                }
+    
+                // Not Null! - we found a tuple with equal or greater key value
+                return true ;
+            }
+    
+            // Less than searches occur below and are not as efficient or easy.
+            // We need to scan up from the begining if findGreaterOrEqual failed
+            // or scan down if findGreaterOrEqual succeed.
+            TupleBrowser l_browser = null ;
+            if(null == l_tuple) {
+                // findGreaterOrEqual failed so we create a tuple and scan from
+                // the lowest values up via getNext comparing each key to a_key
+                l_tuple = new Tuple() ;
+                l_browser = m_bt.browse() ;
+    
+                // We should at most have to read one key.  If 1st key is not
+                // less than or equal to a_key then all keys are > a_key
+                // since the keys are assorted in ascending order based on the
+                // comparator.
+                while(l_browser.getNext(l_tuple)) {
+                    if(m_comparator.compareKey(l_tuple.getKey(), a_key) <= 0) {
+                        return true ;
+                    } else { // Short the search to prevent wasted cycling
+                        return false ;
+                    }
+                }
+            } else {
+                // findGreaterOrEqual succeeded so use the existing tuple and
+                // scan the down from the highest key less than a_key via
+                // getPrevious while comparing each key to a_key.
+                l_browser = m_bt.browse(l_tuple.getKey()) ;
+    
+                // The above call positions the browser just before the given
+                // key so we need to step forward once then back.  Remember this
+                // key represents a key greater than or equal to a_key.
+                if(m_comparator.compareKey(l_tuple.getKey(), a_key) <= 0) {
+                    return true ;
+                }
+                l_browser.getNext(l_tuple) ;
+    
+                // We should at most have to read one key, but we don't short
+                // the search as in the search above first because the chance of
+                // unneccessarily looping is nil since values get smaller.
+                while(l_browser.getPrevious(l_tuple)) {
+                    if(m_comparator.compareKey(l_tuple.getKey(), a_key) <= 0) {
+                        return true ;
+                    }
+                }
+            }
+        } catch(IOException e) {
+            String l_msg = "Failed to lookup whether a key " ;
+            if(isGreaterThan) {
+                l_msg += "greater " ;
+            } else {
+                l_msg += "less " ;
+            }
+            l_msg += "than or equal to a key " + renderKey(a_key)
+                + " exists:\n" + ExceptionUtil.printStackTrace(e) ;
+            throw new BackendException(l_msg, e) ;
+        }
+
+        return false ;
+    }
+
+
+    /**
+     * Checks to see if this table has a key with a specific value.
+     *
+     * @param a_key the key Object to check for
+     * @param a_value the value Object to check for
+     * @return true if a record with the key and value exists, false otherwise.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public boolean has(Object a_key, Object a_value)
+        throws BackendException
+    {
+        if(allowsDuplicates) {
+            TreeSet l_set = (TreeSet) getRaw(a_key) ;
+            if(null == l_set) {
+                return false ;
+            }
+
+            return l_set.contains(a_value) ;
+        }
+
+        Object l_obj = getRaw(a_key) ;
+        if(null == l_obj) {
+            return false ;
+        }
+
+        return l_obj.equals(a_value) ;
+    }
+
+
+    /**
+     * Checks to see if this table has a key: same as a get call with a check to
+     * see if the returned value is null or not.
+     *
+     * @param a_key the Object of the key to check for
+     * @return true if the key exists, false otherwise.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public boolean has(Object a_key)
+        throws BackendException
+    {
+        return getRaw(a_key) != null ;
+    }
+
+
+    /**
+     * Puts a record into this Table.
+     *
+     * @param a_key the key of the record
+     * @param a_value the value of the record.
+     * @return the last value present for a_key or null if this the key did not
+     * exist before. For tables allowing duplicates the return value is null.
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object put(Object a_key, Object a_value)
+        throws BackendException
+    {
+        Object l_replaced = null ;
+
+        if(allowsDuplicates) {
+            TreeSet l_set = (TreeSet) getRaw(a_key) ;
+            if(null == l_set) {
+                l_set = new TreeSet(m_comparator.getValueComparator()) ;
+            } else if(l_set.contains(a_value)) {
+                return a_value ;
+            }
+
+            l_set.add(a_value) ;
+            putRaw(a_key, l_set, true) ;
+            m_count++ ;
+            return null ;
+        }
+
+        l_replaced = putRaw(a_key, a_value, true) ;
+
+        if(null == l_replaced) {
+            m_count++ ;
+        }
+
+        return l_replaced ;
+    }
+
+
+    /**
+     * Removes a single specific record with a_key and a_value from this Table.
+     *
+     * @param the key of the record to remove.
+     * @param the value of the record to remove.
+     * @return a_value if (a_key, a_value) exists to be removed else null
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object remove(Object a_key, Object a_value)
+        throws BackendException
+    {
+        if(allowsDuplicates) {
+            TreeSet l_set = (TreeSet) getRaw(a_key) ;
+
+            if(null == l_set) {
+                return null ;
+            }
+
+            // If removal succeeds then remove if set is empty else replace it
+            if(l_set.remove(a_value)) {
+                if(l_set.isEmpty()) {
+                    removeRaw(a_key) ;
+                } else {
+                    putRaw(a_key, l_set, true) ;
+                }
+
+                // Decrement counter if removal occurs.
+                m_count-- ;
+                return a_value ;
+            }
+
+            return null ;
+        }
+
+        Object l_removed = null ;
+
+        // Remove the value only if it is the same as a_value.
+        if(getRaw(a_key).equals(a_value)) {
+            return removeRaw(a_key) ;
+        }
+
+        return null ;
+    }
+
+
+    /**
+     * Removes all records with a_key from this Table.
+     *
+     * @param the key of the records to remove.
+     * @return if a_key exists its value is returned.  The value will be a
+     * TreeSet containing sorted duplicate values if this table allows
+     * duplicates.
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object remove(Object a_key)
+        throws BackendException
+    {
+        Object l_returned = removeRaw(a_key) ;
+
+        if(null == l_returned) {
+            return null ;
+        }
+
+        if(allowsDuplicates) {
+            TreeSet l_set = (TreeSet) l_returned ;
+            this.m_count -= l_set.size() ;
+            return l_set.first() ;
+        }
+
+        this.m_count-- ;
+        return l_returned ;
+    }
+
+
+    //////////////////////
+    // Cursor Overloads //
+    //////////////////////
+
+
+    /**
+     * Sets a cursor to the first record in the Table and enables single
+     * next steps across all records.
+     *
+     * @throws BackendException if the underlying cursor could not be set.
+     */
+    public Cursor getCursor()
+        throws BackendException
+    {
+        Cursor l_cursor = null ;
+
+        try {
+            l_cursor = new NoDupsCursor(m_bt.browse(), true) ;
+            l_cursor.enableLogging(getLogger()) ;
+        } catch(IOException e) {
+            throw new BackendException("Could not create cursor over table "
+                + m_name + ":\n" + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        if(allowsDuplicates) {
+            l_cursor = new DupsCursor((NoDupsCursor) l_cursor) ;
+            l_cursor.enableLogging(getLogger()) ;
+            return l_cursor ;
+        }
+
+        return l_cursor ;
+    }
+
+
+    /**
+     * Sets a cursor to the first record in the Table with a key value of
+     * a_key and enables single next steps across all duplicate records with
+     * this key.  This cursor will only iterate over duplicates of the key.
+     *
+     * @param a_key the key to iterate over
+     * @throws BackendException if the underlying cursor could not be set
+     */
+    public Cursor getCursor(Object a_key)
+        throws BackendException
+    {
+        if(!allowsDuplicates) {
+            getLogger().warn("JdbmTable.getCursor(Object):"
+                + " Should not be calling this method for tables that"
+                + " do not support duplicates.") ;
+
+            Object l_val = getRaw(a_key) ;
+            if(null == l_val) {
+                return new EmptyCursor() ;
+            } else {
+            	return new SingletonCursor(new Tuple(a_key, getRaw(a_key))) ;
+            }
+        }
+
+        TreeSet l_set = (TreeSet) getRaw(a_key) ;
+        if(l_set == null) {
+            return new EmptyCursor() ;
+        }
+
+        Cursor l_cursor = new TupleIteratorCursor(a_key, l_set.iterator()) ;
+        l_cursor.enableLogging(getLogger()) ;
+        return l_cursor ;
+    }
+
+
+    /**
+     * Sets a cursor to the first record in the Table with a key value
+     * greater/less than or equal to a_key and enables single next steps across
+     * all records with key values equal to or less/greater than a_key.
+     *
+     * @warning This cursor operation has no meaning for database table
+     * types other than the btree type since it relies on sorted keys.
+     * @param a_key the key to use to position this cursor to record with a key
+     * greater/less than or equal to it.
+     * @param isGreaterThan if true the cursor iterates up over ascending keys
+     * greater than or equal to the a_key argument, but if false this cursor
+     * iterates down over descending keys less than or equal to a_key argument.
+     * @throws BackendException if the underlying cursor could not be set
+     */
+    public Cursor getCursor(Object a_key, boolean isGreaterThan)
+        throws BackendException
+    {
+        Cursor l_cursor = null ;
+
+        try {
+            if(isGreaterThan) {
+	            l_cursor = new NoDupsCursor(m_bt.browse(a_key), isGreaterThan) ;
+            } else {
+                /* According to the jdbm docs a browser is positioned right
+                 * before a key greater than or equal to a_key.  getNext() will
+                 * return the next tuple with a key greater than or equal to
+                 * a_key.  getPrevious() used in descending scans for less than
+                 * for equal to comparisions will not.  We need to advance
+                 * forward once and check if the returned Tuple key equals
+                 * a_key.  If it does then we do nothing feeding in the browser
+                 * to the NoDupsCursor.  If it does not we call getPrevious and
+                 * pass it into the NoDupsCursor constructor.
+                 */
+				Tuple l_tuple = new Tuple() ;
+				TupleBrowser l_browser = m_bt.browse(a_key) ;
+                if(l_browser.getNext(l_tuple)) {
+                    Object l_greaterKey = l_tuple.getKey() ;
+                    if(0 != m_comparator.compareKey(a_key, l_greaterKey)) {
+                        // Make sure we don't return l_greaterKey in cursor
+                        l_browser.getPrevious(l_tuple) ;
+                    }
+                }
+
+                // If l_greaterKey != a_key above then it will not be returned.
+                l_cursor = new NoDupsCursor(l_browser, isGreaterThan) ;
+            }
+        } catch(IOException e) {
+            throw new BackendException("Failed to get TupleBrowser on table "
+                + m_name + " using key " + renderKey(a_key) + ":\n"
+                + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        l_cursor.enableLogging(getLogger()) ;
+        if(allowsDuplicates) {
+            l_cursor = new DupsCursor((NoDupsCursor) l_cursor) ;
+            l_cursor.enableLogging(getLogger()) ;
+        }
+
+        return l_cursor ;
+    }
+
+
+    /**
+     * Sets a cursor to the first record in the Table with a key equal to
+     * the a_key argument whose value is greater/less than or equal to a_val and
+     * enables single next steps across all records with key equal to a_key.
+     * Hence this cursor will only iterate over duplicate keys where values are
+     * less/greater than or equal to a_val.
+     *
+     * @warning the underlying Db must have sorted duplicates enabled as in an
+     * Index.
+     * @param a_key the key to use to position this cursor to record with a key
+     * equal to it.
+     * @param a_val the value to use to position this cursor to record with a
+     * value greater/less than or equal to it.
+     * @param isGreaterThan if true the cursor iterates up over ascending values
+     * greater than or equal to the a_val argument, but if false this cursor
+     * iterates down over values less than or equal to a_val argument
+     * descending from the highest values going down.
+     * @throws BackendException if the underlying cursor could not be set or
+     * this method is called over a cursor on a table that does not have sorted
+     * duplicates enabled.
+     */
+    public Cursor getCursor(Object a_key, Object a_val, boolean isGreaterThan)
+        throws BackendException
+    {
+        if(!allowsDuplicates) {
+            getLogger().warn("JdbmTable.getCursor(Object, Object, boolean):"
+                + " Should not be calling this method for tables that"
+                + " do not support duplicates.") ;
+
+            Object l_val = getRaw(a_key) ;
+
+            // key does not exist so return nothing
+            if(null == l_val) {
+				return new EmptyCursor() ;
+            }
+            // l_val == a_val return tuple
+            else if(a_val.equals(l_val)) {
+                return new SingletonCursor(new Tuple(a_key, a_val)) ;
+            }
+			// l_val >= a_val and test is for greater then return tuple
+            else if(m_comparator.compareValue(l_val, a_val) >= 1 &&
+                isGreaterThan)
+            {
+				return new SingletonCursor(new Tuple(a_key, a_val)) ;
+            }
+			// l_val <= a_val and test is for lesser then return tuple
+            else if(m_comparator.compareValue(l_val, a_val) <= 1 &&
+                !isGreaterThan)
+            {
+				return new SingletonCursor(new Tuple(a_key, a_val)) ;
+        	}
+            // key's value does not equal a_val and conditions not satisfied.
+            else {
+                return new EmptyCursor() ;
+            }
+        }
+
+        TreeSet l_set = (TreeSet) getRaw(a_key) ;
+        if(l_set == null) {
+            return new EmptyCursor() ;
+        }
+
+        if(isGreaterThan) {
+            return new TupleIteratorCursor(a_key,
+                l_set.tailSet(a_val).iterator()) ;
+        } else {
+            // Get all values from the smallest upto a_val and put them into
+            // a list.  They will be in ascending order so we need to reverse
+            // the list after adding a_val which is not included in headSet.
+            SortedSet l_headset = l_set.headSet(a_val) ;
+            ArrayList l_list = new ArrayList(l_set.size() + 1) ;
+            l_list.addAll(l_headset) ;
+
+            // Add largest value (a_val) if it is in the set.  TreeSet.headSet
+            // does not get a_val if a_val is in the set.  So we add it now to
+            // the end of the list.  List is now ascending from smallest to
+            // a_val
+            if(l_set.contains(a_val)) {
+                l_list.add(a_val) ;
+            }
+
+            // Reverse the list now we have descending values from a_val to the
+            // smallest value that a_key has.  Return tuple cursor over list.
+            Collections.reverse(l_list) ;
+            return new TupleIteratorCursor(a_key, l_list.iterator()) ;
+        }
+    }
+
+
+    ////////////////////////////
+    // Maintenance Operations //
+    ////////////////////////////
+
+
+    /**
+     * Saves the count of this records to the database file but does not really
+     * close the file since other tables may still be open.  This is because for
+     * Jdbm the RecordManager closes the file.  Many btrees can be stored in a
+     * file.  So this operation mearly performs clean up for this btree.
+     * 
+     * @throws BackendException if there is a failure to save the store the
+     * count data.
+     */
+    public synchronized void close()
+    {
+        try {
+            sync() ;
+        } catch(BackendException e) {
+            getLogger().error("Faild to update and close database:\n", e) ;
+        }
+    }
+
+
+    /**
+     * Does nothing really.  This is because for Jdbm the RecordManager needs
+     * to perform synchronization for the whole file.  This table may be one
+     * btree in that file.  So sychronization is handled higher up.
+     */
+    public void sync() throws BackendException
+    {
+        try {
+            long l_recId = m_recMan.getNamedObject(m_name + SZSUFFIX) ;
+            if(0 == l_recId) {
+				l_recId = m_recMan.insert(new Integer(m_count)) ;
+            } else {
+				m_recMan.update(l_recId, new Integer(m_count)) ;
+            }
+        } catch(IOException e) {
+            throw new BackendException("Failed to update and close database:\n"
+                + ExceptionUtil.printStackTrace(e), e) ;
+        }
+    }
+
+
+    /////////////////////////////
+    // Private Utility Methods //
+    /////////////////////////////
+
+
+    private String render(Object a_key, Object a_value)
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+
+        l_buf.append("('") ;
+        if(null == m_renderer) {
+            l_buf.append(a_key.toString()) ;
+        } else {
+            l_buf.append(m_renderer.getKeyString(a_key)) ;
+        }
+        l_buf.append("', '") ;
+        if(null == m_renderer) {
+            l_buf.append(a_value.toString()) ;
+        } else {
+            l_buf.append(m_renderer.getValueString(a_value)) ;
+        }
+        l_buf.append("')") ;
+
+        return l_buf.toString() ;
+    }
+
+
+    private String renderKey(Object a_obj)
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+
+        l_buf.append('\'') ;
+        if(null == m_renderer) {
+            l_buf.append(a_obj.toString()) ;
+        } else {
+            l_buf.append(m_renderer.getKeyString(a_obj)) ;
+        }
+        l_buf.append('\'') ;
+
+        return l_buf.toString() ;
+    }
+
+
+    private String renderValue(Object a_obj)
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+
+        l_buf.append('\'') ;
+        if(null == m_renderer) {
+            l_buf.append(a_obj.toString()) ;
+        } else {
+            l_buf.append(m_renderer.getValueString(a_obj)) ;
+        }
+        l_buf.append('\'') ;
+
+        return l_buf.toString() ;
+    }
+
+
+    /**
+     * Gets the value of a record by key if the key exists.  If this Table
+     * allows duplicate keys then the first key will be returned.  If this
+     * Table is also a Btree that first key will be the smallest key in the
+     * Table as specificed by this Table's comparator or the default berkeley
+     * bytewise lexical comparator.
+     *
+     * @param a_key the key of the record
+     * @return the value of the Btree tuple which is a TreeSet if this Table
+     * supports duplicates.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    private Object getRaw(Object a_key)
+        throws BackendException
+    {
+        Object l_value = null ;
+
+        try {
+            l_value = m_bt.find(a_key) ;
+        } catch(IOException e) {
+            throw new BackendException("Failed to get value for key "
+                + renderKey(a_key) + ":\n"
+                + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        return l_value ;
+    }
+
+
+    private Object putRaw(Object a_key, Object a_value, boolean doReplace)
+        throws BackendException
+    {
+        Object l_replaced = null ;
+
+        try {
+            l_replaced = m_bt.insert(a_key, a_value, doReplace) ;
+        } catch(IOException e) {
+            throw new BackendException("Failed to insert key value pair "
+                + render(a_key, a_value) + " into table:\n"
+                + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        return l_replaced ;
+    }
+
+
+    private Object removeRaw(Object a_key)
+        throws BackendException
+    {
+        Object l_removed = null ;
+
+        try {
+            l_removed = m_bt.remove(a_key) ;
+        } catch(IOException e) {
+            throw new BackendException(
+                "Failed to remove record with key " + renderKey(a_key)
+                + ":\n" + ExceptionUtil.printStackTrace(e), e) ;
+        }
+
+        return l_removed ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/KeyOnlyComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/KeyOnlyComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,78 @@
+/*
+ * $Id: KeyOnlyComparator.java,v 1.2 2003/03/13 18:27:32 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+public class KeyOnlyComparator
+    implements TupleComparator
+{
+    TableComparator m_keyComparator = null ;
+
+
+    public KeyOnlyComparator(TableComparator a_comparator)
+    {
+        m_keyComparator = a_comparator ;
+    }
+
+
+    /**
+     * Gets the comparator used to compare keys.  May be null in which
+     * case the compareKey method will throw an UnsupportedOperationException.
+     *
+     * @return the comparator for comparing keys.
+     */
+	public TableComparator getKeyComparator()
+    {
+        return m_keyComparator ;
+    }
+
+
+    /**
+     * Will throw an UnsupportedOperationException every time.
+     *
+     * @throws UnsuporredOperation every time.
+     */
+	public TableComparator getValueComparator()
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Compares key Object to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_key1 the first key to compare
+     * @param a_key2 the other key to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second byte array.
+     */
+    public int compareKey(Object a_key1, Object a_key2)
+    {
+        return m_keyComparator.compare(a_key1, a_key2) ;
+    }
+
+
+    /**
+     * Comparse value Objects to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_value1 the first value to compare
+     * @param a_value2 the other value to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second Object.
+     */
+    public int compareValue(Object a_value1, Object a_value2)
+    {
+        throw new UnsupportedOperationException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/MasterTable.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/MasterTable.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,189 @@
+/*
+ * $Id: MasterTable.java,v 1.3 2003/03/13 18:27:33 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import java.io.File ;
+import java.math.BigInteger ;
+import javax.naming.NamingException ;
+
+import org.apache.eve.backend.BackendException ;
+import jdbm.recman.RecordManager;
+import org.apache.eve.backend.jdbm.index.BigIntegerComparator;
+import org.apache.eve.backend.jdbm.index.StringComparator;
+import org.apache.eve.backend.jdbm.index.IndexComparator;
+
+
+/**
+ * The master table used to store LDIF based entries.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ * @testcase org.apache.eve.backend.berkeley.table.TestMasterTable
+ */
+public class MasterTable
+    extends JdbmTable
+{
+    /** the name of the dbf file for this table */
+	public static final String DBF = "master" ;
+    /** the sequence key - stores last sequence value in the admin table */
+    public static final String m_sequence = "__sequence__" ;
+
+    private JdbmTable m_adminTbl = null ;
+
+
+    /**
+     * Creates the master entry table using a Berkeley Db for the backing store.
+     *
+     * @param a_wkdirPath the working directory path where we create the
+     * berkeley database files.
+     * @throws BackendException if there is an error opening the Db file.
+     */
+	public MasterTable(RecordManager a_recMan)
+        throws BackendException
+    {
+        super(DBF, a_recMan, new BigIntegerComparator()) ;
+        m_adminTbl = new JdbmTable("admin", a_recMan, IndexComparator.strComp) ;
+        String l_seqValue = (String) m_adminTbl.get(m_sequence) ;
+        if(null == l_seqValue) {
+            m_adminTbl.put(m_sequence, BigInteger.ZERO.toString()) ;
+        }
+    }
+
+
+    /**
+     * Gets an LDIF record out of this MasterTable corresponding to an entry
+     * with a id.
+     *
+     * @param an_id the BigInteger id of the entry to retrieve.
+     * @return the LDIF of the entry with operational attributes and all.
+     * @throws BackendException if there is a read error on the underlying Db.
+     */
+    public String get(BigInteger an_id)
+        throws BackendException
+    {
+        return (String) super.get(an_id) ;
+    }
+
+
+    /**
+     * Puts a ldif into the master table at an index specified by an_id.  This
+     * is used both to create new entries and update existing ones.
+     *
+     * @param a_ldif the LDIF of the entry with operational attributes and all.
+     * @param an_id the BigInteger id of the entry to put.
+     * @throws BackendException if there is a write error on the underlying Db.
+     */
+    public String put(String a_ldif, BigInteger an_id)
+        throws BackendException
+    {
+        return (String) super.put(an_id, a_ldif) ;
+    }
+
+
+    /**
+     * Deletes a entry from the master table at an index specified by an_id.
+     *
+     * @param an_id the BigInteger id of the entry to delete.
+     * @throws BackendException if there is a write error on the underlying Db.
+     */
+    public String del(BigInteger an_id)
+        throws BackendException, NamingException
+    {
+        return (String) super.remove(an_id) ;
+    }
+
+
+    /**
+     * Get's the current id value from this master database's sequence without
+     * affecting the seq.
+     *
+     * @return the current value.
+     * @throws BackendException if the admin table storing sequences cannot be
+     * read.
+     */
+    public BigInteger getCurrentId()
+        throws BackendException
+    {
+        BigInteger l_id = null ;
+
+        synchronized(m_adminTbl) {
+            l_id = new BigInteger((String) m_adminTbl.get(m_sequence)) ;
+            if(null == l_id) {
+                m_adminTbl.put(m_sequence, BigInteger.ZERO.toString()) ;
+                l_id = BigInteger.ZERO ;
+            }
+        }
+
+        return l_id ;
+    }
+
+
+    /**
+     * Get's the next value from this SequenceBDb.  This has the side-effect of
+     * changing the current sequence values perminantly in memory and on disk.
+     *
+     * @return the current value incremented by one.
+     * @throws BackendException if the admin table storing sequences cannot be
+     * read and writen to.
+     */
+    public BigInteger getNextId()
+        throws BackendException
+    {
+        BigInteger l_lastVal = null ;
+        BigInteger l_nextVal = null ;
+
+        synchronized(m_adminTbl) {
+            l_lastVal = new BigInteger((String) m_adminTbl.get(m_sequence)) ;
+            if(null == l_lastVal) {
+                m_adminTbl.put(m_sequence, BigInteger.ONE.toString()) ;
+                return BigInteger.ONE ;
+            } else {
+                l_nextVal = l_lastVal.add(BigInteger.ONE) ;
+                m_adminTbl.put(m_sequence, l_nextVal.toString()) ;
+            }
+        }
+
+        return (l_nextVal) ;
+    }
+
+
+    /**
+     * Gets a persistant property stored in the admin table of this MasterTable.
+     *
+     * @param a_property the key of the property to get the value of
+     * @return the value of the property
+     * @throws BackendException when the underlying admin table cannot be read
+     */
+	public String getProperty(String a_property)
+        throws BackendException
+    {
+        synchronized(m_adminTbl) {
+    	    return (String) m_adminTbl.get(a_property) ;
+        }
+    }
+
+
+    /**
+     * Sets a persistant property stored in the admin table of this MasterTable.
+     *
+     * @param a_property the key of the property to set the value of
+     * @param a_value the value of the property
+     * @throws BackendException when the underlying admin table cannot be writen
+     */
+	public void setProperty(String a_property, String a_value)
+        throws BackendException
+    {
+        synchronized(m_adminTbl) {
+            m_adminTbl.put(a_property, a_value) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/NoDupsCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/NoDupsCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,108 @@
+/*
+ * $Id: NoDupsCursor.java,v 1.3 2003/03/13 18:27:33 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException ;
+
+import jdbm.helper.TupleBrowser ;
+import jdbm.helper.Tuple;
+import java.io.IOException ;
+import javax.naming.NamingException ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+
+
+/**
+ * A simple cursor over a TupleBrowser on a table that does not allow
+ * duplicates.
+ * 
+ * @warning The Tuple returned by this Cursor is always the same instance object
+ * returned every time. It is reused to for the sake of efficency rather than
+ * creating a new tuple for each advance() call.
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public class NoDupsCursor
+    extends Cursor
+{
+    private final Tuple m_returned = new Tuple() ;
+    private final Tuple m_prefetched = new Tuple() ;
+    private final TupleBrowser m_browser ;
+    private final boolean doAscendingScan ;
+
+    protected boolean canAdvance = true ;
+
+
+    /**
+     * Creates a cursor over a TupleBrowser where duplicates are not expected.
+     */
+    NoDupsCursor(TupleBrowser a_browser, boolean doAscendingScan)
+        throws BackendException
+    {
+        m_browser = a_browser ;
+        this.doAscendingScan = doAscendingScan ;
+        prefetch() ;
+    }
+
+
+    boolean doAscendingScan()
+    {
+        return this.doAscendingScan ;
+    }
+
+
+    void prefetch()
+        throws BackendException
+    {
+        // Prefetch into tuple!
+        boolean isSuccess = false ;
+
+        try {
+            if(doAscendingScan) {
+                isSuccess = m_browser.getNext(m_prefetched) ;
+            } else {
+                isSuccess = m_browser.getPrevious(m_prefetched) ;
+            }
+        } catch(IOException e) {
+            throw new BackendException("Could not advance cursor due to "
+                + " TupleBrowser failure:\n"
+                + ExceptionUtil.printStackTrace(e)) ;
+        }
+
+        if(!isSuccess) {
+            canAdvance = false ;
+            try { close() ; } catch(NamingException e) { /* Never thrown */ }
+        }
+    }
+
+
+    protected Object advance()
+        throws BackendException
+    {
+        m_returned.setKey(m_prefetched.getKey()) ;
+        m_returned.setValue(m_prefetched.getValue()) ;
+
+        prefetch() ;
+
+        return m_returned ;
+    }
+
+
+    protected boolean canAdvance()
+    {
+        return canAdvance ;
+    }
+
+
+    public void freeResources() { /* Does nothing! */ }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/Table.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/Table.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,288 @@
+/*
+ * $Id: Table.java,v 1.2 2003/03/13 18:27:34 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.backend.BackendException ;
+
+
+/**
+ * A backend friendly wrapper around a jdbm BTree that transparent enables
+ * duplicates when the BTree does not support them.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface Table
+{
+    /**
+     * Gets the comparator used by this Table: may be null if this Table was
+     * not initialized with one.
+     *
+     * @return the final comparator instance or null if this Table was not
+     * created with one.
+     */
+    public TupleComparator getComparator() ;
+
+    /**
+     * Gets the data renderer used by this Table to display or log records keys
+     * and values.
+     *
+     * @return the renderer used
+     */
+    public TupleRenderer getRenderer() ;
+
+    /**
+     * Sets the data renderer to by used by this Table to display or log record
+     * keys and values.
+     *
+     * @param a_renderer the DataRenderer instance to used as the renderer.
+     */
+    public void setRenderer(TupleRenderer a_renderer) ;
+
+    /**
+     * Gets the name of this Table.
+     *
+     * @return the name
+     */
+    public String getName() ;
+
+    /**
+     * Checks to see if this Table has enabled the use of duplicate keys.
+     *
+     * @return true if duplicate keys are enabled, false otherwise.
+     */
+	public boolean isDupsEnabled() ;
+
+    /**
+     * Checks to see if this Table has enabled sorting on the values of
+     * duplicate keys.
+     *
+     * @return true if duplicate key values are sorted, false otherwise.
+     */
+	public boolean isSortedDupsEnabled() ;
+
+    ///////////////////////////////////////
+    // Simple Table Key/Value Assertions //
+    ///////////////////////////////////////
+
+    /**
+     * Checks to see if this table has a key: same as a get call with a check to
+     * see if the returned value is null or not.
+     *
+     * @param a_key the Object of the key to check for
+     * @return true if the key exists, false otherwise.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public boolean has(Object a_key) throws BackendException ;
+
+    /**
+     * Checks to see if this table has a key with a specific value.
+     *
+     * @param a_key the key Object to check for
+     * @param a_value the value Object to check for
+     * @return true if a record with the key and value exists, false otherwise.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public boolean has(Object a_key, Object a_value) throws BackendException ;
+
+    /**
+     * Checks to see if this table has a record with a key greater/less than or
+     * equal to the key argument.  The key argument need not exist for this
+     * call to return true.  The underlying database must be a BTree because
+     * this method depends on the use of sorted keys.
+     *
+     * @param a_key the key Object to compare keys to
+     * @param isGreaterThan boolean for greater than or less then comparison
+     * @return true if a record with a key greater/less than the key argument
+     * exists, false otherwise
+     * @throws BackendException if there is a failure to read the underlying Db,
+     * or if the underlying Db is not a Btree.
+     */
+	public boolean has(Object a_key, boolean isGreaterThan)
+        throws BackendException ;
+
+    /**
+     * Checks to see if this table has a record with a key equal to the
+     * argument key with a value greater/less than or equal to the value
+     * argument provided.  The key argument <strong>MUST</strong> exist for
+     * this call to return true and the underlying Db must be a Btree that
+     * allows for sorted duplicate values.  The entire basis to this method
+     * depends on the fact that duplicate key values are sorted according to
+     * a valid value comparator function.
+     *
+     * @param a_key the key Object
+     * @param a_val the value Object to compare values to
+     * @param isGreaterThan boolean for greater than or less then comparison
+     * @return true if a record with a key greater/less than the key argument
+     * exists, false otherwise
+     * @throws BackendException if there is a failure to read the underlying Db
+     * or if the underlying Db is not of the Btree type that allows sorted
+     * duplicate values.
+     */
+	public boolean has(Object a_key, Object a_val, boolean isGreaterThan)
+        throws BackendException ;
+
+    ////////////////////////////////////
+    // Table Value Accessors/Mutators //
+    ////////////////////////////////////
+
+    /**
+     * Gets the value of a record by key if the key exists.  If this Table
+     * allows duplicate keys then the first key will be returned.  If this
+     * Table is also a Btree that first key will be the smallest key in the
+     * Table as specificed by this Table's comparator or the default berkeley
+     * bytewise lexical comparator.
+     *
+     * @param a_key the key of the record
+     * @return the value of the record with a_key if a_key exists or null if
+     * no such record exists.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public Object get(Object a_key) throws BackendException ;
+
+    /**
+     * Puts a record into this Table.
+     *
+     * @param a_key the key of the record
+     * @param a_value the value of the record.
+     * @return the last value present for a_key or null if this the key did not
+     * exist before.
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object put(Object a_key, Object a_value) throws BackendException ;
+
+    /**
+     * Removes all records with a_key from this Table.
+     *
+     * @param the key of the records to remove.
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object remove(Object a_key) throws BackendException ;
+
+    /**
+     * Removes a single specific record with a_key and a_value from this Table.
+     *
+     * @param the key of the record to remove.
+     * @param the value of the record to remove.
+     * @throws BackendException if there is a failure to read or write to
+     * the underlying Db
+     */
+    public Object remove(Object a_key, Object a_value) throws BackendException ;
+
+    //////////////////////
+    // Cursor Overloads //
+    //////////////////////
+
+    /**
+     * Sets a cursor to the first record in the Table and enables single
+     * next steps across all records.
+     *
+     * @throws BackendException if the underlying cursor could not be set.
+     */
+    public Cursor getCursor() throws BackendException ;
+
+    /**
+     * Sets a cursor to the first record in the Table with a key value of
+     * a_key and enables single next steps across all duplicate records with
+     * this key.  This cursor will only iterate over duplicates of the key.
+     *
+     * @param a_key the key to iterate over
+     * @throws BackendException if the underlying cursor could not be set
+     */
+    public Cursor getCursor(Object a_key) throws BackendException ;
+
+    /**
+     * Sets a cursor to the first record in the Table with a key value
+     * greater/less than or equal to a_key and enables single next steps across
+     * all records with key values equal to or less/greater than a_key.
+     *
+     * @warning This cursor operation has no meaning for database table
+     * types other than the btree type since it relies on sorted keys.
+     * @param a_key the key to use to position this cursor to record with a key
+     * greater/less than or equal to it.
+     * @param isGreaterThan if true the cursor iterates up over ascending keys
+     * greater than or equal to the a_key argument, but if false this cursor
+     * iterates down over descending keys less than or equal to a_key argument.
+     * @throws BackendException if the underlying cursor could not be set
+     */
+    public Cursor getCursor(Object a_key, boolean isGreaterThan)
+        throws BackendException ;
+
+    /**
+     * Sets a cursor to the first record in the Table with a key equal to
+     * the a_key argument whose value is greater/less than or equal to a_key and
+     * enables single next steps across all records with key equal to a_key.
+     * Hence this cursor will only iterate over duplicate keys where values are
+     * less than or greater than or equal to a_val.
+     *
+     * @warning the underlying Db must have sorted duplicates enabled as in an
+     * Index.
+     * @param a_key the key to use to position this cursor to record with a key
+     * equal to it.
+     * @param a_val the value to use to position this cursor to record with a
+     * value greater/less than or equal to it.
+     * @param isGreaterThan if true the cursor iterates up over ascending values
+     * greater than or equal to the a_val argument, but if false this cursor
+     * iterates down over descending values less than or equal to a_val argument
+     * starting from the largest value going down.
+     * @throws BackendException if the underlying cursor could not be set or
+     * this method is called over a cursor on a table that does not have sorted
+     * duplicates enabled.
+     */
+    public Cursor getCursor(Object a_key, Object a_val, boolean isGreaterThan)
+        throws BackendException ;
+
+    ////////////////////////////////
+    // Table Record Count Methods //
+    ////////////////////////////////
+
+    /**
+     * Gets the count of the number of records in this Table.
+     *
+     * @return the number of records
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count() throws BackendException ;
+
+    /**
+     * Gets the count of the number of records in this Table with a specific
+     * key: returns the number of duplicates for a key.
+     *
+     * @param a_key the Object key to count.
+     * @return the number of duplicate records for a key.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count(Object a_key) throws BackendException ;
+
+    /**
+     * Returns the number of records greater than or less than a key value.  The
+     * key need not exist for this call to return a non-zero value.
+     *
+     * @param a_key the Object key to count.
+     * @param isGreaterThan boolean set to true to count for greater than and
+     * equal to record keys, or false for less than or equal to keys.
+     * @return the number of keys greater or less than a_key.
+     * @throws BackendException if there is a failure to read the underlying Db
+     */
+    public int count(Object a_key, boolean isGreaterThan) throws BackendException ;
+
+    /**
+     * Closes the underlying Db of this Table.
+     * 
+     * @throws BackendException if there is a failure to close the handle to
+     * the underlying Db file.
+     */
+    public void close() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TableComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TableComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,26 @@
+/*
+ * $Id: TableComparator.java,v 1.2 2003/03/13 18:27:34 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+/**
+ * Doc me!
+ * @todo Doc me!
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public abstract class TableComparator
+    extends jdbm.helper.Comparator
+    implements java.util.Comparator
+{
+    public abstract int compare( Object an_obj1, Object an_obj2 ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleComparator.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleComparator.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,64 @@
+/*
+ * $Id: TupleComparator.java,v 1.3 2003/03/13 18:27:34 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+/**
+ * Used to compare the sorting order of binary data.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public interface TupleComparator
+{
+    /**
+     * Gets the comparator used to compare keys.  May be null in which
+     * case the compareKey method will throw an UnsupportedOperationException.
+     *
+     * @return the comparator for comparing keys.
+     */
+	TableComparator getKeyComparator() ;
+
+
+    /**
+     * Gets the binary comparator used to compare valuess.  May be null in which
+     * case the compareValue method will throw an UnsupportedOperationException.
+     *
+     * @return the binary comparator for comparing values.
+     */
+	TableComparator getValueComparator() ;
+
+
+    /**
+     * Compares key Object to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_key1 the first key to compare
+     * @param a_key2 the other key to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second byte array.
+     */
+    int compareKey(Object a_key1, Object a_key2) ;
+
+
+    /**
+     * Comparse value Objects to determine their sorting order returning a
+     * value = to, < or > than 0.
+     *
+     * @param a_value1 the first value to compare
+     * @param a_value2 the other value to compare to the first
+     * @return 0 if both are equal, a negative value less than 0 if the first
+     * is less than the second, or a postive value if the first is greater than
+     * the second Object.
+     */
+    int compareValue(Object a_value1, Object a_value2) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleIteratorCursor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleIteratorCursor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,64 @@
+/*
+ * $Id: TupleIteratorCursor.java,v 1.2 2003/03/13 18:27:35 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import java.util.Iterator ;
+import org.apache.eve.backend.Cursor;
+import jdbm.helper.Tuple;
+
+
+/**
+ * A cursor using an underlying Iterator.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class TupleIteratorCursor
+    extends Cursor
+{
+    private final Object m_key ;
+    private final Iterator m_iterator ;
+    private final Tuple m_tuple = new Tuple() ;
+
+
+    /**
+     * Creates a cursor over an Iterator.
+     * 
+     * @param a_iterator the underlying iterator this cursor uses.
+     */
+    public TupleIteratorCursor(Object a_key, Iterator a_iterator)
+    {
+        m_key = a_key ;
+        m_tuple.setKey(a_key) ;
+        m_iterator = a_iterator ;
+    }
+
+
+    /** Returns iterator.next() */
+    public Object advance()
+    {
+        m_tuple.setKey(m_key) ;
+        m_tuple.setValue(m_iterator.next()) ;
+        return m_tuple ;
+    }
+
+
+    /** Returns iterator.hasNext() */
+    public boolean canAdvance()
+    {
+        return m_iterator.hasNext() ;
+    }
+
+
+    /** Does nothing */
+    public void freeResources() { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleRenderer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/jdbm/table/TupleRenderer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,45 @@
+/*
+ * $Id: TupleRenderer.java,v 1.2 2003/03/13 18:27:35 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.backend.jdbm.table ;
+
+
+import org.apache.eve.backend.BackendException ;
+
+
+/**
+ * A table key/value String renderer for the display or logging of
+ * human readable potentially binary data.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface TupleRenderer
+{
+    /**
+     * Gets the key Object rendered as a String.
+     *
+     * @param a_key the key Object
+     * @return the String representation of the key Object
+     * @throws BackendException if there is a backend failure while trying to
+     * interpret the key.
+     */
+    String getKeyString(Object a_key) ;
+
+    /**
+     * Gets the value Object rendered as a String.
+     *
+     * @param a_value the value Object
+     * @return the String representation of the value Object
+     * @throws BackendException if there is a backend failure while trying to
+     * interpret the value.
+     */
+    String getValueString(Object a_value) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/package.html
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/backend/package.html	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,4 @@
+
+<p><font color="#999999">$Id: package.html,v 1.1.1.1 2002/11/13 23:46:12 akarasulu Exp $</font> </p>
+<p>The backend package defines interfaces that must be implemented by all Backend 
+  modules. </p>

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: ClientException.java,v 1.2 2003/03/13 18:27:03 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/** This exception is thrown when protocol errors occurred */
+public class ClientException extends CascadingRuntimeException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ClientException(String message, Throwable t)
+    {
+        super(message, t) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ClientException(String message)
+    {
+        super(message, null) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientKey.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientKey.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,286 @@
+/*
+ * $Id: ClientKey.java,v 1.5 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import java.net.Socket ;
+import java.net.InetAddress ;
+
+
+/**
+ * Every client that successfully binds anonymously or with a valid identity
+ * has a unique client key represented by this class.  First and foremost the
+ * key is used to uniquely identify the client based on the interface and
+ * port used to connection on the server as well as the interface and port used
+ * by the client.
+ *
+ * The ClientKey plays a central role in coordinating activities with the
+ * server across various threads.  Threads within the same stage or across
+ * stages are synchronized on client resources using lock objects held by a
+ * ClientKey instance.  Socket IO is managed using a pair of lock objects
+ * specificially for this purpose.  As the need arises more lock objects may be
+ * used for specific client resources like a session object.  These extra lock
+ * objects are now being discussed.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.5 $
+ */
+public final class ClientKey
+{
+    // ----------------------------------------------
+    // Private members.
+    // ----------------------------------------------
+
+    /** Input channel synchronization object */
+    private final Object m_inputLock = new Object() ;
+    /** Output channel synchronization object */
+    private final Object m_outputLock = new Object() ;
+    /** Server socket interface address */
+    private final InetAddress m_serverAddress ;
+    /** Client socket interface address */
+    private final InetAddress m_clientAddress ;
+	/** Whether or not this key has expired: the client has disconnected. */
+    private boolean m_hasExpired = false ;
+
+    // ----------------------------------------------
+    // pkg-friendly final members: made so the public
+    // accessors do not need to be used by classes in
+    // this pkg - need access to these members for
+    // cleanup operations after expiration.  Do not
+    // want to unnecessarily throw an exception.
+    // ----------------------------------------------
+
+	/** Unique key or client id */
+    final String m_clientId ;
+    /** Server socket TCP port on server host */
+    final int m_serverPort ;
+    /** Client socket TCP port on client host */
+    final int m_clientPort ;
+
+
+    // ----------------------------------------------
+    // Constructors
+    // ----------------------------------------------
+
+
+    /**
+      * Generates a unique connection/client identifier String for a client
+      * socket connection.  The key is composed of the local server address
+      * and port attached to the remote client address and port.  If the
+      * server ip and port are 192.168.1.1:1389 and the client's ip and port are
+      * 34.23.12.1:5678 then the key string would be:
+      *
+      * 192.168.1.1:1389<-34.23.12.1:5678
+      *
+      * This makes the key unique at any single point in time.
+      *
+      * @param a_socket newly established client socket connection to the
+      * server.
+      */
+    ClientKey( final Socket a_socket )
+    {
+        // Extract properties needed to formulate the client id ( key ).
+        m_serverPort = a_socket.getLocalPort() ;
+        m_serverAddress = a_socket.getLocalAddress() ;
+        m_clientPort = a_socket.getPort() ;
+        m_clientAddress = a_socket.getInetAddress() ;
+
+        // Build the key
+        StringBuffer l_buf =
+            new StringBuffer(m_serverAddress.getHostAddress()) ;
+        l_buf.append(':').append(m_serverPort).append("<-") ;
+        l_buf.append(m_clientAddress.getHostAddress()).append(':') ;
+        l_buf.append(m_clientPort) ;
+        m_clientId = l_buf.toString() ;
+    }
+
+
+    // ----------------------------------------------
+    // Accessors of conn. parameters to client id
+    // ----------------------------------------------
+
+
+    /**
+     * Get the unique client id for a connected client based on connection
+     * parameters.
+     *
+     * @return the unique id of the client connection
+     * @throws KeyExpiryException to force the handling of expired keys rather
+     * than depending on developers to maintain a convention of checking for
+     * key expiration before use in other modules.
+     */
+    public String getClientId()
+        throws KeyExpiryException
+    {
+        checkExpiry() ;
+        return m_clientId ;
+    }
+
+
+    /**
+     * Gets the client's IP address.
+     *
+     * @return the client's ip address.
+     * @throws KeyExpiryException to force the handling of expired keys
+     */
+    public String getClientAddress()
+        throws KeyExpiryException
+    {
+        checkExpiry() ;
+		return m_clientAddress.getHostAddress() ;
+    }
+
+
+    /**
+     * Gets the client's hostname.
+     *
+     * @return the client's hostname.
+     * @throws KeyExpiryException to force the handling of expired keys
+     */
+    public String getClientHost()
+        throws KeyExpiryException
+    {
+        checkExpiry() ;
+        return m_clientAddress.getHostName() ;
+    }
+
+
+    // ----------------------------------------------
+    // ClientKey lock object accessors.
+    // ----------------------------------------------
+
+
+    /**
+     * Gets the client's output stream lock object.
+     *
+     * @return ouput lock object.
+     * @throws KeyExpiryException to force the handling of expired keys
+     */
+    public Object getOutputLock()
+        throws KeyExpiryException
+    {
+        checkExpiry() ;
+        return m_outputLock ;
+    }
+
+
+    /**
+     * Gets the client's input stream lock object.
+     *
+     * @return input lock object.
+     * @throws KeyExpiryException to force the handling of expired keys
+     */
+    public Object getInputLock()
+        throws KeyExpiryException
+    {
+        checkExpiry() ;
+        return m_inputLock ;
+    }
+
+
+    // ----------------------------------------------
+    // Key expiration methods.
+    // ----------------------------------------------
+
+
+    /**
+     * Determines if the client represented by this ClientKey is still
+     * connected to the server.  Once disconnected the ClientKey is expired
+     * by the server so processing on behalf of the client does not continue.
+     *
+     * @return true if the client is no longer connected to the server, false
+     * if the client is connected.
+     */
+    public boolean hasExpired()
+    {
+        return m_hasExpired ;
+    }
+
+
+    /**
+     * Expires this key to indicate the disconnection of the client represented
+     * by this key from the server.  It is intentionally package friendly to
+     * only allow access by the ClientModule.
+     */
+    void expire()
+    {
+        m_hasExpired = true ;
+    }
+
+
+    /**
+     * Utility method to throw key expiration exception if this ClientKey has
+     * expired.  This method is called by most accessor methods within this
+     * class with <code>hasExpired()</code> being the only exception.  The
+     * purpose for this is to force ClientKey using modules to check for
+     * expiration rather rely upon them to check to see if the key is valid
+     * before use everytime.
+     * 
+     * @throws KeyExpiryException to force the handling of expired keys rather
+     * than depending on developers to maintain a convention of checking for
+     * key expiration before use in other modules.
+     */
+    private void checkExpiry()
+        throws KeyExpiryException
+    {
+        if(m_hasExpired) {
+            throw new KeyExpiryException() ;
+        }
+    }
+
+
+    // ----------------------------------------------
+    // Class java.lang.Object method overrides.
+    // ----------------------------------------------
+
+
+    /**
+     * For debugging returns the clientId string.
+     *
+     * @return the client id string.
+     */
+    public String toString()
+    {
+        return m_clientId ;
+    }
+
+
+    /**
+     * Gets the hashCode of the unique clientId String.  Overriden to correctly
+     * manage ClientKey's within Map based collections.
+     *
+     * @return the clientId hashCode value.
+     */
+    public int hashCode()
+    {
+        return m_clientId.hashCode() ;
+    }
+
+
+    /**
+     * Determines whether this ClientKey is equivalent to another.  If argument
+     * object is not the same reference the clientId String's are compared using
+     * the <code>String.equal()</code> method.  Required for containment within
+     * collections.
+     *
+     * @return true if an_obj equals this ClientKey, false otherwise.
+     */
+    public boolean equals(Object an_obj)
+    {
+        if(this == an_obj) {
+            return true ;
+        } else if(an_obj instanceof ClientKey) {
+            return ((ClientKey) an_obj).m_clientId.equals(m_clientId) ;
+        }
+
+        return false ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,123 @@
+/*
+ * $Id: ClientManager.java,v 1.7 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import java.net.Socket ;
+import java.io.IOException ;
+import java.io.InputStream ;
+
+import org.apache.eve.event.OutputListener ;
+import org.apache.eve.event.ConnectListener ;
+import org.apache.eve.security.LdapPrincipal ;
+import javax.naming.ldap.LdapContext;
+
+
+/**
+ * Service interface used to manage clients, their connections and their
+ * stateful sessions.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.7 $
+ */
+public interface ClientManager
+    extends ConnectListener
+{
+    /** role played by this service interface */
+    String ROLE = ClientManager.class.getName() ;
+
+    /**
+     * Drops a client connection and destroys the client's session.
+     *
+     * @param a_clientKey the key used to uniquely identify this client.
+     */
+    void drop( ClientKey a_clientKey ) ;
+
+    /**
+     * Drops a client connection and destroys the client's session associated
+     * with the calling thread.
+     */
+    void drop() ;
+
+    /**
+     * Creates a client session using the client's unique key.
+     * 
+     * @param a_clientKey the client key used to uniquely identify the client.
+     * @param a_socket a client socket to the server.
+     */
+    ClientSession add( ClientKey a_clientKey, Socket a_socket )
+        throws IOException ;
+
+    /**
+     * Sets the user principal for a client on a bind operation.  The protocol
+     * states that a bind operation requires the destruction of all outstanding
+     * operations.  Hence all outstanding operations refered to by the client's
+     * key must be terminated, the session parameters are flushed, then the
+     * princal is set.  The client affectively changes its role without dropping
+     * the socket connection.
+     *
+     * @param a_clientKey the client's unique key.
+     * @param a_principal the new principal to be taken on by the client using
+     * the existing socket connection.
+     */
+    ClientSession
+        setUserPrincipal( ClientKey a_clientKey, LdapPrincipal a_principal ) ;
+
+    /**
+     * Explicit access to a client's session by the client's ClientKey.
+     *
+     * @param a_clientKey the client's unique key
+     * @return the session associated with the client's key.
+     */
+    ClientSession getClientSession( ClientKey a_clientKey ) ;
+
+    /**
+     * Gets the client session associated with the calling thread's context.
+     *
+     * @return the client's session which the current thread is doing work for.
+     */
+    ClientSession getClientSession() ;
+
+    /**
+     * Gets the key of the client on whose behalf the current thread is
+     * executing.
+     *
+     * @return the ClientKey associated with the callers thread or null if none
+     * exists.
+     */
+	ClientKey getClientKey() ;
+
+    /**
+     * Gets the LdapContext associated with the calling thread.
+     *
+     * @return the context of the caller thread
+     */
+    LdapContext getLdapContext() ;
+
+    /**
+     * Associates an external thread using the JNDI provider with a LdapContext.
+     *
+     * @param a_ctx the LdapContext to be associated with the calling thread.
+     */
+    void threadAssociate( LdapContext a_ctx ) ;
+
+    /**
+     * Associates a protocol request handler driving thread with a client.
+     *
+     * @param a_clientKey the unique ClientKey associated with the request.
+     */
+    void threadAssociate( ClientKey a_clientKey ) ;
+
+    /**
+     * Disassociates a protocol request handler driving thread with a client.
+     */
+    void threadDisassociate() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManagerSlave.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientManagerSlave.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,15 @@
+/*
+ * $Id: ClientManagerSlave.java,v 1.2 2003/03/13 18:27:04 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+public interface ClientManagerSlave
+{
+    void registerClientManager(ClientManager a_clientManager) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,509 @@
+/*
+ * $Id: ClientModule.java,v 1.13 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.EventObject ;
+
+import java.net.Socket ;
+
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.OutputStream ;
+import java.io.PushbackInputStream ;
+import java.io.BufferedOutputStream ;
+
+import org.apache.eve.decoder.Decoder ;
+import org.apache.eve.event.InputEvent ;
+import org.apache.eve.event.OutputEvent ;
+import org.apache.eve.input.InputModule ;
+import org.apache.eve.seda.AbstractStage ;
+import org.apache.eve.event.ConnectEvent ;
+import org.apache.eve.event.EventHandler ;
+import org.apache.eve.input.InputManager ;
+import org.apache.eve.output.OutputModule ;
+import org.apache.eve.output.OutputManager ;
+import org.apache.eve.security.LdapPrincipal ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.protocol.ProtocolEngine ;
+import org.apache.eve.event.AbstractEventHandler ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.cornerstone.services.threads.ThreadManager ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+import javax.naming.ldap.LdapContext;
+
+
+/**
+ * ClientManager service implementation used to manage client sessions and
+ * their socket connections.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.client.ClientManager"
+ * @phoenix:mx-topic name="client-manager"
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.13 $
+ */
+public class ClientModule
+    extends AbstractStage
+    implements ClientManager
+{
+    public static final String SOCKETLISTENER_POOL = "client" ;
+
+    private Map m_sockets = new HashMap() ;
+    private Map m_sessions = new HashMap() ;
+	private Decoder m_decoder = null ;
+    private InputManager m_inputManager = null ;
+    private OutputManager m_outputManager = null ;
+    private UnifiedBackend m_nexus = null ;
+    private ProtocolEngine m_engine = null ;
+
+    /**
+     * We are using a ThreadLocal just as a means to key into a session based
+     * on the current thread of execution which has been associated with a
+     * session using the threadAssociate method.  This is done to enable backend
+     * modules to access the session of the user performing operations without
+     * having to pass around the user session.  The ThreadLocal actually maps
+     * the Thread to the ClientKey.  <code>getClientSession()</code> without
+     * arguments simply accesses the ClientKey using the current executing
+     * Thread as the key into this ThreadLocal.  The ClientKey is then used to
+     * return the ClientSession via another lookup into the m_sessions Map.
+     */
+    private ThreadLocal m_threadKeys = new ThreadLocal() ;
+
+    /**
+     * Thread outside of the protocol manager making calling nexus and backend
+     * methods through the JNDI provider need to propagate context environment
+     * parameters without passing is as an argument one each call.  This Thread
+     * Local maps threads to JNDI contexts.
+     */
+    private ThreadLocal m_threadCtxs = new ThreadLocal() ;
+
+
+    // ---------------------------------------------------------
+    // Constructors
+    // ---------------------------------------------------------
+
+
+    /**
+     * Default constructor creates the client module by initializing a
+     * ConnectEventHandler for it.
+     */
+    public ClientModule()
+    {
+        m_handler = new ConnectEventHandler() ;
+    }
+
+
+    // ---------------------------------------------------------
+    // Stage Event Handler Class: ConnectionEventHandler
+    // ---------------------------------------------------------
+
+
+    /**
+     * The stage event handler for the ClientModule.  This class processes
+     * incomming ConnectEvents thrown by the ServerListener service.
+     */
+    class ConnectEventHandler extends AbstractEventHandler
+    {
+        /**
+         * Primary event handling method to process a ConnectEvent.
+         *
+         * @param an_event must be a ConnectEvent subtype of EventObject
+         */
+        public void handleEvent( EventObject an_event )
+        {
+            Socket l_socket = null ;
+            Logger l_log = ClientModule.this.getLogger() ;
+            ClientKey l_clientKey = null ;
+            ConnectEvent l_event = null ;
+
+            try
+            {
+                if( an_event instanceof ConnectEvent )
+                {
+                    l_event = ( ConnectEvent ) an_event ;
+                    l_socket = ( Socket ) l_event.getSource() ;
+                    l_clientKey = new ClientKey( l_socket ) ;
+                    add( l_clientKey, l_socket ) ;
+                }
+                else
+                {
+                    l_log.error( "Unknown event " + an_event + " ignored" ) ;
+                }
+            }
+            catch( Throwable t )
+            {
+                l_log.error( "Droping client " + l_clientKey
+                    + " on handler error: ", t ) ;
+                drop( l_clientKey ) ;
+            }
+        }
+    }
+
+
+    // ---------------------------------------------------------
+    // Add/Drop/Get ClientSession Management Methods
+    // ---------------------------------------------------------
+
+
+    /**
+     * Drops a client connection and destroys the client's session associated
+     * with the calling thread.
+     */
+    public void drop()
+    {
+    	drop( getClientKey() ) ;
+    }
+
+
+    /**
+     * Drops a client connection by unregistering the client with io managers
+     * and closing the client socket connection.
+     *
+     * @param a_clientKey the key of the client to drop
+     */
+    public void drop( ClientKey a_clientKey )
+    {
+        Socket l_socket = null ;
+        ClientSession l_session = null ;
+
+        // Unregister client key with io manager and expire it.
+        m_inputManager.unregister( a_clientKey ) ;
+        m_outputManager.unregister( a_clientKey ) ;
+        a_clientKey.expire() ;
+
+        // Remove client session from session map
+        synchronized( m_sessions )
+        {
+            l_session = ( ClientSession ) m_sessions.remove( a_clientKey ) ;
+        }
+
+        // Invalidate removed session to disable use by held handles to session
+        if( l_session != null )
+        {
+            l_session.invalidate() ;
+        }
+
+        // Remove client socket
+        synchronized( m_sockets )
+        {
+            l_socket = ( Socket ) m_sockets.remove( a_clientKey ) ;
+        }
+
+        // Close the client socket
+        if( null != l_socket )
+        {
+            try
+            {
+	            l_socket.close() ;
+            }
+            catch( IOException e )
+            {
+                String l_msg = "Could not close client " + a_clientKey
+                    + " socket!" ;
+                getLogger().error( l_msg, e ) ;
+                throw new ClientException( l_msg, e ) ;
+            }
+        }
+    }
+
+
+    /**
+     * Adds a client connection by registering the client io streams with the
+     * io managers and tracking the client using the supplied client key.  The
+     * client's session is initialized using an anonymous principal.  Later
+     * bind operations can change the session principal to represent the
+     * appropriate user.
+     *
+     * @param a_clientKey the key of the client to add.
+     * @param a_socket the client's socket.
+     */
+    public ClientSession add( ClientKey a_clientKey, Socket a_socket )
+        throws IOException
+    {
+        LdapClientSession l_session = null ;
+
+        // map client key to socket.
+        synchronized( m_sockets )
+        {
+            m_sockets.put( a_clientKey, a_socket ) ;
+        }
+
+        // Register Socket IO streams with the respective IO manager
+        m_inputManager.register( a_clientKey, a_socket.getInputStream() ) ;
+        m_outputManager.register( a_clientKey, a_socket.getOutputStream() ) ;
+
+        // Create a client session using the default principal (anonymous)
+        // which corresponds to an empty string for the distinguished name.
+        l_session = new LdapClientSession( a_clientKey, new LdapPrincipal() ) ;
+	    m_sessions.put( a_clientKey, l_session ) ;
+        return l_session ;
+    }
+
+
+    /**
+     * Sets the user principal for a client on a bind operation.  The protocol
+     * states that a bind operation requires the destruction of all outstanding
+     * operations.  Hence all outstanding operations refered to by the client's
+     * key must be terminated, the session parameters are flushed, then the
+     * princal is set.  The client affectively changes its role without dropping
+     * the socket connection.
+     *
+     * @todo need to make sure we stop all outstanding request operations before
+     * changing the principal of the user.
+     * @param a_clientKey the client's unique key.
+     * @param a_principal the new principal to be taken on by the client using
+     * the existing socket connection.
+     */
+    public ClientSession
+        setUserPrincipal( ClientKey a_clientKey, LdapPrincipal a_principal )
+    {
+        /** @todo */
+        // Must destroy existing operations here before changing the principal
+        LdapClientSession l_session = ( LdapClientSession )
+            m_sessions.get( a_clientKey ) ;
+
+        // We need to completely replace the session, expire the old key and
+        // create a new one and go from there rather than reseting the session
+        // we want old handles to be useless to both these objects and we
+        // want the code possessing it to be aware when it tries to use it.
+
+        // This is the only way to stop outstanding requests that are in stages
+        // other than those that are in the protocol engine stage.  We basically
+        // need to destroy and recreate everything except the socket connection.
+
+        l_session.reset() ;
+        l_session.setPrincipal( a_principal ) ;
+        return l_session ;
+    }
+
+
+    /**
+     * Gets the ClientSession associated with the ClientKey argument.
+     *
+     * @param a_clientKey the unique client primary key
+     * @return the session of the client
+     */
+    public ClientSession getClientSession( ClientKey a_clientKey )
+    {
+        return ( ClientSession ) m_sessions.get( a_clientKey ) ;
+    }
+
+
+    /**
+     * Gets the key of the client on whose behalf the current thread is
+     * executing.
+     *
+     * @return the ClientKey associated with the callers thread or null if none
+     * exists.
+     */
+	public ClientKey getClientKey()
+    {
+		return ( ClientKey ) m_threadKeys.get() ;
+    }
+
+
+    /**
+     * Gets the ClientKey associated within the context of the calling Thread.
+     *
+     * @see threadAssociate()
+     * @see threadDisassociate()
+     * @return the session of the client associated with the calling Thread
+     */
+    public ClientSession getClientSession()
+    {
+        ClientKey l_key = ( ClientKey ) m_threadKeys.get() ;
+        return ( ClientSession ) m_sessions.get( l_key ) ;
+    }
+
+
+    /**
+     * Gets the LdapContext associated with the calling thread.
+     *
+     * @return the context of the caller thread
+     */
+    public LdapContext getLdapContext()
+    {
+        return ( LdapContext ) m_threadCtxs.get() ;
+    }
+
+
+    /**
+     * Associates the calling thread with a client using a ClientKey.  A call to
+     * this method enables calls to getClientSession() without arguments to
+     * return a non-null ClientSession handle.
+     *
+     * @param a_clientKey the unique client primary key
+     */
+    public void threadAssociate( ClientKey a_clientKey )
+    {
+	    m_threadKeys.set( a_clientKey ) ;
+    }
+
+
+    /**
+     * Associates the calling thread with a JNDI LdapContext.  A call to
+     * this method enables calls to getLdapContext() without arguments to
+     * return an LdapContext handle.
+     *
+     * @param a_ctx the LdapContext to associate with the calling thread
+     */
+    public void threadAssociate( LdapContext a_ctx )
+    {
+	    this.m_threadCtxs.set( a_ctx ) ;
+    }
+
+
+    /**
+     * Disassociates the calling thread with a client.  After a call to this
+     * method the calling thread cannot acquire a non-null handle on a
+     * ClientSession object through a call to getClientSession() without
+     * arguments.
+     */
+    public void threadDisassociate()
+    {
+        if( m_threadKeys.get() != null )
+        {
+        	m_threadKeys.set( null ) ;
+        }
+        else
+        {
+        	m_threadCtxs.set( null ) ;
+        }
+    }
+
+
+    // ---------------------------------------------------------
+    // Listener Implementations
+    // ---------------------------------------------------------
+
+
+    /**
+     * ConnectListener interface implementation which asynchronously processes
+     * the ConnectEvent generated by the ServerListener service.  It merely
+     * enqueues the event onto this Stage's event queue and returns immediately
+     * without processing the event in the thread of the caller.
+     *
+     * @param an_event a client connection event.
+     */
+    public void connectPerformed( ConnectEvent an_event )
+        throws CascadingRuntimeException
+    {
+        enqueue( an_event ) ;
+    }
+
+
+    // ---------------------------------------------------------
+    // Module & Life-Cycle Methods
+    // ---------------------------------------------------------
+
+
+    /**
+     * Overriden to enable handler after enabling this Module via a super
+     * method invokation.
+     *
+     * @param a_logger the logger to set this module and its handler to use
+     */
+    public void enableLogging( Logger a_logger )
+    {
+        super.enableLogging( a_logger ) ;
+        m_handler.enableLogging( a_logger ) ;
+    }
+
+
+    /**
+     * Gets the ROLE of the service this Module implements.
+     *
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the service interface (ROLE)
+     * @phoenix:mx-isWriteable no
+     * @return the role of this service.
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets a descriptive name for this module's implementation.
+     *
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the implementation name
+     * @phoenix:mx-isWriteable no
+     * @return descriptive implementation name.
+     */
+    public String getImplementationName()
+    {
+        return "Client Manager Module" ;
+    }
+
+
+    /**
+     * Gets the fully qualified class name of this service implementation class.
+     *
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the implementation class name
+     * @phoenix:mx-isWriteable no
+     * @return FQCN of this class.
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+	/**
+     * Gets a handle on various services minux the ThreadManager which is
+     * accessed by the service method of the AbstractStage superclass.
+     * 
+     * @phoenix:dependency name="org.apache.eve.decoder.Decoder"
+     * @phoenix:dependency name="org.apache.eve.input.InputManager"
+     * @phoenix:dependency name="org.apache.eve.output.OutputManager"
+     * @phoenix:dependency name="org.apache.eve.backend.UnifiedBackend"
+     * @phoenix:dependency name="org.apache.eve.protocol.ProtocolEngine"
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+     */
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        super.service( a_manager ) ;
+        m_decoder = ( Decoder ) a_manager.lookup( Decoder.ROLE ) ;
+        m_nexus = ( UnifiedBackend ) a_manager.lookup( UnifiedBackend.ROLE ) ;
+        m_engine = ( ProtocolEngine ) a_manager.lookup( ProtocolEngine.ROLE ) ;
+        m_inputManager = ( InputManager )
+            a_manager.lookup( InputManager.ROLE ) ;
+        m_outputManager = ( OutputManager )
+            a_manager.lookup( OutputManager.ROLE ) ;
+    }
+
+
+    /**
+     * Initializes this module by registering it with various slave modules like
+     * the InputManager, OutputManager and ProtocolEngine services.
+     */
+    public void initialize()
+        throws Exception
+    {
+        m_nexus.registerClientManager( this ) ;
+        m_engine.registerClientManager( this ) ;
+        m_inputManager.registerClientManager( this ) ;
+        m_outputManager.registerClientManager( this ) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientSession.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ClientSession.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,62 @@
+/*
+ * $Id: ClientSession.java,v 1.4 2003/08/22 21:15:55 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import java.util.Locale ;
+import java.util.Iterator;
+
+import org.apache.eve.security.LdapPrincipal ;
+
+
+
+public interface ClientSession
+{
+    ClientKey getClientKey() ;
+
+    ////////////////////////////
+    // Session Attribute APIs //
+    ////////////////////////////
+
+    boolean isValid() ;
+
+    Iterator getAttributeNames() ;
+
+    Object getAttribute(String an_attrName) ;
+
+    void removeAttribute(String an_attrName) ;
+
+    void setAttribute(String an_attrName, Object a_attrValue) ;
+
+    void invalidate() ;
+
+    boolean isNew() ;
+
+    long getCreationTime() ;
+
+    long getLastAccessedTime() ;
+
+    int getMaxInactiveInterval() ;
+
+    void setMaxInactiveInterval(int an_interval) ;
+
+    //ServerConfig getServerConfig() ;
+
+
+    /////////////////////////
+    // Session Client APIs //
+    /////////////////////////
+
+
+    Locale getLocale() ;
+
+    LdapPrincipal getPrincipal() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/KeyExpiryException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/KeyExpiryException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,28 @@
+/*
+ * $Id: KeyExpiryException.java,v 1.1 2003/03/22 19:55:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client;
+
+/**
+ * Exception thrown when an accessor method is used on an expired ClientKey
+ */
+public class KeyExpiryException extends Exception {
+    /** Constructs an Exception without a message. */
+    public KeyExpiryException() {
+        super();
+    }
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public KeyExpiryException(String message) {
+        super(message);
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/LdapClientSession.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/LdapClientSession.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,156 @@
+/*
+ * $Id: LdapClientSession.java,v 1.2 2003/08/22 21:15:55 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.client ;
+
+
+import java.util.Locale ;
+import java.util.Iterator ;
+import java.util.Hashtable ;
+import java.util.Observable ;
+
+import org.apache.eve.security.LdapPrincipal ;
+
+
+public class LdapClientSession
+    extends Observable
+    implements ClientSession
+{
+    public static final int MAX_INACTIVE_INTERVAL = 900 ;
+
+    private final long m_creationTime = System.currentTimeMillis() ;
+    private final Hashtable m_attribs = new Hashtable() ;
+
+    protected boolean m_isNew = true ;
+    protected boolean m_isValid = true ;
+    protected int m_maxInactiveInterval = MAX_INACTIVE_INTERVAL ;
+    protected long m_lastAccessedTime = m_creationTime ;
+    protected final ClientKey m_clientKey ;
+    protected LdapPrincipal m_principal = null ;
+    protected ServerConfig m_serverConfig = null ;
+
+
+    public LdapClientSession(ClientKey a_clientKey, LdapPrincipal a_principal)
+    {
+        m_clientKey = a_clientKey ;
+        m_principal = a_principal ;
+    }
+
+
+    ////////////////////////////
+    // Session Attribute APIs //
+    ////////////////////////////
+
+
+    public Object getAttribute(String an_attrName)
+    {
+        return m_attribs.get(an_attrName) ;
+    }
+
+
+    public void removeAttribute(String an_attrName)
+    {
+        m_attribs.remove(an_attrName) ;
+    }
+
+
+    public void setAttribute(String an_attrName, Object a_attrValue)
+    {
+        m_attribs.put(an_attrName, a_attrValue) ;
+    }
+
+
+    public Iterator getAttributeNames()
+    {
+        return m_attribs.keySet().iterator() ;
+    }
+
+
+    public void invalidate()
+    {
+        m_isValid = false ;
+        m_attribs.clear() ;
+        super.setChanged() ;
+    }
+
+
+    public ClientKey getClientKey()
+    {
+        return m_clientKey ;
+    }
+
+
+    public boolean isNew()
+    {
+        return m_isNew ;
+    }
+
+
+    public long getCreationTime()
+    {
+        return m_creationTime ;
+    }
+
+
+    public long getLastAccessedTime()
+    {
+        return m_lastAccessedTime ;
+    }
+
+
+    public int getMaxInactiveInterval()
+    {
+        return m_maxInactiveInterval ;
+    }
+
+
+    public void setMaxInactiveInterval(int a_maxInactiveInterval)
+    {
+        m_maxInactiveInterval = a_maxInactiveInterval ;
+    }
+
+
+    /////////////////////////
+    // Session Client APIs //
+    /////////////////////////
+
+
+    public Locale getLocale()
+    {
+        return m_principal.getLocale() ;
+    }
+
+
+    public LdapPrincipal getPrincipal()
+    {
+        return m_principal ;
+    }
+
+
+    public void setPrincipal(LdapPrincipal a_principal)
+    {
+        m_principal = a_principal ;
+    }
+
+
+    public boolean isValid()
+    {
+        return m_isValid ;
+    }
+
+
+    void reset() {
+        m_attribs.clear() ;
+        m_isNew = true ;
+        m_isValid = true ;
+        m_maxInactiveInterval = MAX_INACTIVE_INTERVAL ;
+        m_lastAccessedTime = System.currentTimeMillis() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ServerConfig.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/client/ServerConfig.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,22 @@
+/*
+ * $Id: ServerConfig.java,v 1.2 2003/03/13 18:27:08 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+package org.apache.eve.client ;
+
+
+
+import java.util.Iterator ;
+
+
+public interface ServerConfig
+{
+    String getServerName() ;
+    String getInitParameter(String a_paramName) ;
+    Iterator getInitParameterNames() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/Decoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/Decoder.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,29 @@
+/*
+ * $Id: Decoder.java,v 1.4 2003/03/26 02:09:15 jmachols Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.decoder ;
+
+
+import org.apache.eve.event.InputListener ;
+
+
+/**
+ * Service interface for decoding an ASN.1 BER encoded stream to demarshal
+ * LDAP protocol request messages.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: jmachols $
+ * @version $Revision: 1.4 $
+ */
+public interface Decoder
+    extends InputListener
+{
+    /** Role played by the service as defined in Avalon */
+    String ROLE = Decoder.class.getName() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: DecoderException.java,v 1.2 2003/03/13 18:27:09 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.decoder ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/** This exception is thrown when protocol errors occurred */
+public class DecoderException extends CascadingRuntimeException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public DecoderException(String message, Throwable t)
+    {
+        super(message, t) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public DecoderException(String message)
+    {
+        super(message, null) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/decoder/DecoderModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,246 @@
+/*
+ * $Id: DecoderModule.java,v 1.8 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.decoder ;
+
+
+import java.io.InputStream ;
+import java.util.EventObject ;
+
+import org.apache.ldap.common.message.Request ;
+import org.apache.ldap.common.message.MessageDecoder ;
+
+import org.apache.eve.event.InputEvent ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.event.RequestEvent ;
+import org.apache.eve.seda.AbstractStage ;
+import org.apache.eve.client.KeyExpiryException ;
+import org.apache.eve.protocol.ProtocolEngine ;
+import org.apache.eve.event.AbstractEventHandler ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+
+
+/**
+ * Decoder service implemented as a stage for ASN.1 Binary encoded LDAPv3 data.
+ * 
+ * @phoenix:block
+ * @phoenix:mx-topic name="DecoderModule"
+ * @phoenix:service name="org.apache.eve.decoder.Decoder"
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.8 $
+ */
+public class DecoderModule
+    extends AbstractStage
+    implements Decoder
+{
+    /** Handle on the ldap request protocol processing engine */
+    private ProtocolEngine m_engine = null ;
+
+    /** MessageDecoder used to decode messages in a provider independent way. */
+    private MessageDecoder m_msgDecoder = null ;
+
+
+    // ------------------------------------------------------------------------
+    // Default Constructor
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates an instance of the Decoder service module.  Initializes the
+     * stage's event handler so the next life-cycle method can enable logging.
+     * 
+     * @todo look into the correct way to enable logging in these handlers while
+     * making their instantiation reside within the initialize life-cycle
+     * method.
+     */
+    public DecoderModule()
+    {
+        m_handler = new InputEventHandler() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // InputListener Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * InputListener interface method implementation enabling this DecoderModule
+     * to detect the reception of InputEvents.  Simply enqueues the event onto
+     * this Stage's event queue returning immediately thereafter.  The event is
+     * processed by this Stage's event handler.
+     *
+     * @param a_event InputEvent encapsulating the ClientKey and the client
+     * Socket's InputStream.
+     */
+    public void inputReceived( InputEvent a_event )
+    {
+        enqueue( a_event ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Module Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets this Module implementation's service interface (a.k.a its role)
+     *
+     * @return the service interface name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the service interface (ROLE)
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets this Module implementation's descriptive name.
+     *
+     * @return descriptive module name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the descriptive name
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "ASN.1 LDAPv3 BER Decoder Module" ;
+    }
+
+
+    /**
+     * Gets this Module implementation's fully qualified class name.
+     *
+     * @return the fqcn
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the FQCN
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Avalon Life-Cycle Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Method override to make sure that the handler's logger is initialized
+     * after calling the super method.
+     *
+     * @param a_logger the Logger for this module.
+     */
+    public void enableLogging( Logger a_logger )
+    {
+        super.enableLogging( a_logger ) ;
+        m_handler.enableLogging( a_logger ) ;
+    }
+
+
+    /**
+     * Initialization instantiates the MessageDecoder.
+     *
+     * @todo see if there is any value in adding an optional configuration
+     * parameter to switch the BER library provider based on a configuration
+     * property for this module.
+     */
+    public void initialize() throws Exception
+    {
+        m_msgDecoder = new MessageDecoder() ;
+    }
+
+
+	/**
+     * Grabs handle directly on ProtocolEngine yet super call grabs the
+     * ThreadManager.
+     * 
+     * @phoenix:dependency name="org.apache.eve.protocol.ProtocolEngine"
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+     */
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        super.service( a_manager ) ;
+        m_engine = ( ProtocolEngine ) a_manager.lookup( ProtocolEngine.ROLE ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Decoder EventHandler Implementation Class
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Decoder stage EventHandler implementation whose handleEvent method is the
+     * primary work function driven by this stage's worker threads.
+     */
+	class InputEventHandler extends AbstractEventHandler
+    {
+        /**
+         * Handles an InputEvent by decoding the binary encoded byte stream
+         * contained within a_event parameter in a BER Library provider
+         * independant fashion.
+         *
+         * @param a_event the InputEvent as an EventObject.
+         */
+        public void handleEvent( EventObject a_event )
+        {
+            Object l_lock = null ;
+            InputStream l_in = null ;
+	        InputEvent l_event = null ;
+            ClientKey l_clientKey = null ;
+
+            // Check first event type is correct
+	        if( ! ( a_event instanceof InputEvent ) )
+            {
+	            throw new DecoderException( "Unrecognized event: " + a_event ) ;
+	        }
+
+            // Extract event info and init local vars
+	        l_event = ( InputEvent ) a_event ;
+	        l_clientKey = ( ClientKey ) l_event.getSource() ;
+	        l_in = l_event.getInputStream() ;
+
+            // Obtain input lock object or return.
+            try
+            {
+                l_lock = l_clientKey.getInputLock() ;
+            }
+            catch( KeyExpiryException e )
+            {
+                if( getLogger().isWarnEnabled() )
+                {
+	                getLogger().warn( "ClientKey for " + l_clientKey
+                        + " has expired right after server accept: ", e ) ;
+                }
+
+                return ;
+            }
+
+            // Decode the request, build the event and deliver to the engine
+            Request l_request = ( Request )
+                m_msgDecoder.decode( l_lock, l_in ) ;
+            RequestEvent l_requestEvent =
+                new RequestEvent( l_clientKey, l_request ) ;
+	        m_engine.requestReceived( l_requestEvent ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/Encoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/Encoder.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,41 @@
+/*
+ * $Id: Encoder.java,v 1.4 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.encoder ;
+
+
+import org.apache.ldap.common.message.Response ;
+
+import org.apache.eve.event.ResponseListener ;
+
+
+/**
+ * Avalon service interface for a module that encodes a Response using Basic
+ * Encoding Rules into an LDAPv3 Protocol Data Unit (PDU) that can be delivered
+ * over the wire.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public interface Encoder
+    extends ResponseListener
+{
+    String ROLE = Encoder.class.getName() ;
+
+    /**
+     * Synchronously encodes an LDAPv3 protocol Response message into a byte
+     * buffer that can be written to a Stream as an BER encoded PDU.
+     *
+     * @param a_response the LDAP Response message to be encoded.
+     */
+    public byte [] encode( Response a_response )
+        throws EncoderException ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: EncoderException.java,v 1.2 2003/03/13 18:27:12 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.encoder ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/** This exception is thrown when protocol errors occurred */
+public class EncoderException extends CascadingRuntimeException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public EncoderException(String message, Throwable t)
+    {
+        super(message, t) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public EncoderException(String message)
+    {
+        super(message, null) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/encoder/EncoderModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,283 @@
+/*
+ * $Id: EncoderModule.java,v 1.6 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.encoder ;
+
+
+import java.util.EventObject ;
+import java.io.ByteArrayInputStream ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+import org.apache.ldap.common.message.Response ;
+import org.apache.ldap.common.message.MessageEncoder ;
+import org.apache.ldap.common.message.MessageException ;
+
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.event.OutputEvent ;
+import org.apache.eve.seda.AbstractStage ;
+import org.apache.eve.event.ResponseEvent ;
+import org.apache.eve.output.OutputManager ;
+import org.apache.eve.event.AbstractEventHandler ;
+
+
+/**
+ * Encodes Protocol Data Unit (PDU) using Basic Encoding (BER) Rules.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.encoder.Encoder"
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.6 $
+ */
+public class EncoderModule
+    extends AbstractStage
+    implements Encoder
+{
+    /** Handle on the output manager which recieves events from this module. */
+    private OutputManager m_outputManager = null ;
+
+    /** Encoding machinery from the message/BERlib provider framework. */
+    private MessageEncoder m_msgEncoder = null ;
+
+
+    // ------------------------------------------------------------------------
+    // Default Constructor
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Constructor initializes this stage's event handler by instantiating a
+     * ResponseEventHandler which is a named inner class.  The event handler is
+     * used to process events after they are dequeued off of the stage's event
+     * queue.  The handler's handleEvent is called with an EventObject by stage
+     * worker threads which drive event handling.  Pesently this is instantiated
+     * here because rather than within the initialize method because the handler
+     * is LogEnabled when the EncoderModule is in the enableLogging life-cycle
+     * method.
+     *
+     * @todo look into the correct way to enable logging in these handlers while
+     * making their instantiation reside within the initialize life-cycle
+     * method.
+     */
+    public EncoderModule()
+    {
+        m_handler = new ResponseEventHandler() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Encoder Service Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Synchronously encodes an LDAPv3 protocol Response message into a byte
+     * buffer that can be written to a Stream as an BER encoded PDU.
+     *
+     * @param a_response the LDAP Response message to be encoded.
+     */
+    public byte [] encode( Response a_response )
+        throws EncoderException
+    {
+        byte [] l_buf = null ;
+
+        try
+        {
+            l_buf = m_msgEncoder.encode( a_response ) ;
+        }
+        catch( MessageException me )
+        {
+            getLogger().error( "Encoder error: ", me ) ;
+            throw new EncoderException( "Encoder error: ", me ) ;
+        }
+
+        return l_buf ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // ResponseListener Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Listener's handler method simply enqueues the ResponseEvent on this
+     * stage's event queue for asynchronous processing by stage worker threads.
+     *
+     * @param a_event the ResponseEvent to handle.
+     */
+    public void responseComposed( ResponseEvent a_event )
+        throws CascadingRuntimeException
+    {
+	    enqueue( a_event ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Module Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the service interface name of this module.
+     *
+     * @return the role of this module's implemented service.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the service role name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets the name of the implementation.  For example the name of the
+     * Berkeley DB Backend module is "Berkeley DB Backend".
+     *
+     * @return String representing the module implementation type name.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "ASN.1 BER Encoder Module" ;
+    }
+
+
+    /**
+     * Gets the name of the implementation class.  For example the name of the
+     * Berkeley DB Backend implementation class is <code>
+     * "ldapdd.backend.berkeley.BackendBDb" </code>.
+     *
+     * @return String representing the module implementation's class name.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation class name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Avalon Framework Life-Cycle Methods
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Log enables the handler right after calling the super method.
+     *
+     * @param a_logger the logger used by this module.
+     */
+    public void enableLogging( Logger a_logger )
+    {
+        super.enableLogging( a_logger ) ;
+        m_handler.enableLogging( a_logger ) ;
+    }
+
+
+    /**
+     * Initialization instantiates the MessageEncoder.
+     *
+     * @todo see if there is any value in adding an optional configuration
+     * parameter to switch the BER library provider based on a configuration
+     * property for this module.
+     */
+    public void initialize() throws Exception
+    {
+        m_msgEncoder = new MessageEncoder() ;
+    }
+
+
+    /**
+     * Service method grabs a handle on the OutputManager directly and its
+     * super method implementation grabs a handler on the cornerstone
+     * ThreadManager for getting the stage's thread pool.
+     * 
+     * @phoenix:dependency name="org.apache.eve.output.OutputManager"
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+	 */
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        super.service( a_manager ) ;
+        m_outputManager = ( OutputManager )
+            a_manager.lookup( OutputManager.ROLE ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Stage EventHandler Class Definition
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Stage event handler class definition.
+     */
+    class ResponseEventHandler extends AbstractEventHandler
+    {
+        /**
+         * Check and cast a response event. Then processes event by encoding
+         * the response into a byte [] buffer using the parent class' encode
+         * method.  Builds the OutputEvent and delivers it to the OutputManager.
+         *
+         * @param an_event the ResponseEvent to process.
+         */
+	    public void handleEvent( EventObject an_event )
+        {
+	        if( ! ( an_event instanceof ResponseEvent ) )
+            {
+	            throw new EncoderException( "Unrecognized event: "
+                    + an_event ) ;
+	        }
+
+            ResponseEvent l_event = ( ResponseEvent ) an_event ;
+
+            try {
+	            if( ! ( an_event instanceof ResponseEvent ) )
+                {
+	                throw new EncoderException("Unrecognized event: " +
+                        l_event) ;
+	            }
+	    
+	            ClientKey l_client = ( ClientKey ) an_event.getSource() ;
+                byte [] l_buf = encode( l_event.getResponse() ) ;
+	            ByteArrayInputStream l_in = new ByteArrayInputStream( l_buf ) ;
+	    
+	            if( getLogger().isDebugEnabled() )
+                {
+	                getLogger().debug( "Response encoded for client "
+                        + l_client ) ;
+                    getLogger().debug( "About to hand off response to client "
+                        + "manager within encoder event") ;
+                }
+
+                OutputEvent l_outEvent = new OutputEvent( l_client, l_in ) ;
+                m_outputManager.writeResponse( l_outEvent ) ;
+	    
+	            if( getLogger().isDebugEnabled() )
+                {
+	                getLogger().debug( "Handed off OutputEvent for client "
+                        + l_client + " to OutputManager" ) ;
+	            }
+	        } catch(Throwable t) {
+	            getLogger().error( "Encoder Stage Handler: ", t ) ;
+	        }
+	    }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AbstractEventHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AbstractEventHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,19 @@
+/*
+ * $Id: AbstractEventHandler.java,v 1.2 2003/03/13 18:27:14 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+
+public abstract class AbstractEventHandler
+    extends AbstractLogEnabled
+    implements EventHandler
+{
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,36 @@
+/*
+ * $Id: AuthenticationEvent.java,v 1.2 2003/03/13 18:27:14 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventObject ;
+
+import org.apache.eve.client.ClientKey ;
+import java.security.Principal ;
+
+
+public class AuthenticationEvent
+    extends EventObject
+{
+    final Principal m_principal ;
+
+
+    public AuthenticationEvent(ClientKey a_client, Principal a_principal)
+    {
+        super(a_client) ;
+        m_principal = a_principal ;
+    }
+
+
+    public Principal getPrincipal()
+    {
+        return m_principal ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/AuthenticationListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,15 @@
+/*
+ * $Id: AuthenticationListener.java,v 1.2 2003/03/13 18:27:15 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event;
+
+public interface AuthenticationListener
+{
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,49 @@
+/*
+ * $Id: ClientEvent.java,v 1.2 2003/03/13 18:27:16 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.net.Socket ;
+import java.util.EventObject ;
+import org.apache.eve.client.ClientKey ;
+
+
+public class ClientEvent
+    extends EventObject
+{
+    public final static int DROP_EVENT = 0 ;
+    public final static int ADD_EVENT = 1 ;
+    public final static int OUTPUT_EVENT = 2 ;
+    public final static int INPUT_EVENT = 3 ;
+    public final static int REQUEST_EVENT = 4 ;
+    public final static int RESPONSE_EVENT = 5 ;
+    public final static int AUTH_EVENT = 6 ;
+
+    public final int type ;
+
+
+    public ClientEvent(ClientKey a_client, int a_type)
+    {
+        super(a_client) ;
+        type = a_type ;
+    }
+
+
+    public ClientKey getClientKey()
+    {
+        return (ClientKey) this.source ;
+    }
+
+
+    public int getType()
+    {
+        return type ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ClientListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,16 @@
+/*
+ * $Id: ClientListener.java,v 1.2 2003/03/13 18:27:17 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+public interface ClientListener
+{
+    void clientAdded(ClientEvent a_client) ;
+    void clientDropped(ClientEvent a_client) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,24 @@
+/*
+ * $Id: ConnectEvent.java,v 1.2 2003/03/13 18:27:17 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.net.Socket ;
+import java.util.EventObject;
+
+
+public class ConnectEvent
+    extends EventObject
+{
+    public ConnectEvent(Socket a_socket)
+    {
+        super(a_socket) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ConnectListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,21 @@
+/*
+ * $Id: ConnectListener.java,v 1.3 2003/03/13 18:27:18 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventListener ;
+
+
+public interface ConnectListener
+    extends EventListener
+{
+    void connectPerformed(ConnectEvent an_event) ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,23 @@
+/*
+ * $Id: EntryEvent.java,v 1.2 2003/03/13 18:27:19 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventObject ;
+
+
+public class EntryEvent
+    extends EventObject
+{
+    public EntryEvent(Object a_source)
+    {
+        super(a_source) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEventSource.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryEventSource.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,17 @@
+/*
+ * $Id: EntryEventSource.java,v 1.2 2003/03/13 18:27:19 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+public interface EntryEventSource
+{
+    void addEntryListener(EntryListener a_listener) ;
+    void removeEntryListener(EntryListener a_listener) ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EntryListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,21 @@
+/*
+ * $Id: EntryListener.java,v 1.2 2003/03/13 18:27:20 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+import java.util.EventListener ;
+
+public interface EntryListener
+    extends EventListener
+{
+    void entryAdded(EntryEvent an_event) ;
+    void entryChanged(EntryEvent an_event) ;
+    void entryRemoved(EntryEvent an_event) ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EventHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/EventHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,42 @@
+/*
+ * $Id: EventHandler.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventObject ;
+import java.util.EventListener ;
+
+import org.apache.avalon.framework.logger.LogEnabled ;
+import org.apache.avalon.framework.service.Serviceable ;
+import org.apache.avalon.framework.context.Contextualizable ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/**
+ * Event handler used by Stages.
+ *
+ * @todo Should this even be LogEnabled? Not a good idea I think. Let's think
+ * about refactoring this later down the road.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public interface EventHandler
+    extends EventListener, LogEnabled
+{
+    /**
+     * Exception is explicitly made to be a runtime exception so it can tunnel
+     * up through the run() call of handler Runnable.
+     *
+     * @param a_event the event to process or handle.
+     */
+    void handleEvent( EventObject a_event ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,35 @@
+/*
+ * $Id: InputEvent.java,v 1.2 2003/03/13 18:27:20 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+import java.util.EventObject ;
+import java.io.InputStream ;
+import org.apache.eve.client.ClientKey;
+
+
+public class InputEvent
+    extends EventObject
+{
+    private final InputStream m_in ;
+
+
+    public InputEvent(ClientKey a_client, InputStream a_in)
+    {
+        super(a_client) ;
+        m_in = a_in ;
+    }
+
+
+    public InputStream getInputStream()
+    {
+        return m_in ;
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/InputListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,19 @@
+/*
+ * $Id: InputListener.java,v 1.2 2003/03/13 18:27:21 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+import org.apache.avalon.framework.CascadingException;
+import java.util.EventListener;
+
+
+public interface InputListener
+    extends EventListener
+{
+    void inputReceived(InputEvent an_event) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,33 @@
+/*
+ * $Id: OutputEvent.java,v 1.2 2003/03/13 18:27:21 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+import java.io.InputStream ;
+import java.util.EventObject;
+import org.apache.eve.client.ClientKey;
+
+
+public class OutputEvent
+    extends ClientEvent
+{
+    private final InputStream m_in ;
+
+    public OutputEvent(final ClientKey a_client, final InputStream a_dataStream)
+    {
+        super(a_client, OUTPUT_EVENT) ;
+        m_in = a_dataStream ;
+    }
+
+
+    public InputStream getInputStream()
+    {
+        return m_in ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/OutputListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,21 @@
+/*
+ * $Id: OutputListener.java,v 1.2 2003/03/13 18:27:22 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+import java.util.EventListener;
+
+
+public interface OutputListener
+    extends EventListener
+{
+    void writeResponse(OutputEvent an_event) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,56 @@
+/*
+ * $Id: RequestEvent.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventObject ;
+
+import org.apache.ldap.common.message.Request ;
+import org.apache.eve.client.ClientKey ;
+
+
+/**
+ * Event which announces the arrival of a LDAPv3 client request.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public class RequestEvent
+    extends EventObject
+{
+    /** The decoded request associated with this event. */
+    private final Request m_request ;
+
+
+    /**
+     * Creates an event wrapper around a client key and a request for that
+     * client.
+     *
+     * @param a_clientKey the unique key identifying a client.
+     * @param a_request the request object associated with this event.
+     */
+    public RequestEvent( final ClientKey a_clientKey, final Request a_request )
+    {
+        super( a_clientKey ) ;
+        m_request = a_request ;
+    }
+
+
+    /**
+     * Gets the client request associated with this event.
+     *
+     * @return the client Request.
+     */
+    public Request getRequest()
+    {
+        return m_request ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/RequestListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,30 @@
+/*
+ * $Id: RequestListener.java,v 1.3 2003/03/13 18:27:24 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventListener ;
+import org.apache.avalon.framework.CascadingException ;
+
+
+/**
+ * Generic interface extended by the ProtocolEngine service interface to enable
+ * the receipt of RequestEvents encapsulating a client's request PDU.
+ */
+public interface RequestListener
+    extends EventListener
+{
+    /**
+     * RequestEvent handler of the listener.
+     *
+     * @param an_event a RequestEvent encapsulating the client's request PDU.
+     */
+    void requestReceived(RequestEvent an_event) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,56 @@
+/*
+ * $Id: ResponseEvent.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventObject ;
+
+import org.apache.eve.client.ClientKey ;
+import org.apache.ldap.common.message.Response ;
+
+
+/**
+ * An event representing the composition of a response to a client request.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.3 $
+ */
+public class ResponseEvent
+    extends EventObject
+{
+    /** The Reponse composed for a client request. */
+    private final Response m_response ;
+
+
+    /**
+     * Creates a ResponseEvent for a client identified by a key on a response.
+     *
+     * @param a_clientKey a unique client identifying key.
+     * @param a_response the response this event announces the composition of.
+     */
+    public ResponseEvent( final ClientKey a_clientKey,
+        final Response a_response )
+    {
+        super( a_clientKey ) ;
+        m_response = a_response ;
+    }
+
+
+    /**
+     * Gets the response object associated with this event.
+     *
+     * @return the LDAPv3 Response message.
+     */
+    public Response getResponse()
+    {
+        return m_response ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/ResponseListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,35 @@
+/*
+ * $Id: ResponseListener.java,v 1.4 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event ;
+
+
+import java.util.EventListener ;
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/**
+ * Components which listen for the composition of a response.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public interface ResponseListener
+    extends EventListener
+{
+    /**
+     * Listener's handler method to take action upon the reciept of a
+     * ResponseEvent.
+     *
+     * @param a_event the ResponseEvent to handle.
+     */
+    void responseComposed( ResponseEvent a_event ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AbandonEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AbandonEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,26 @@
+/*
+ * $Id: AbandonEvent.java,v 1.2 2003/03/13 18:27:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import java.util.EventObject ;
+
+
+/**
+ * Event which logically represents a protocol abandon operation.
+ */
+public class AbandonEvent
+    extends ProtocolEvent
+{
+    public AbandonEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, ABANDONREQUEST_MASK, a_isPduDelivered) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AddEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/AddEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,72 @@
+/*
+ * $Id: AddEvent.java,v 1.4 2003/04/09 15:51:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.directory.Attributes ;
+import javax.naming.Name;
+import javax.naming.directory.DirContext;
+
+
+/**
+ * Event which logically represents a protocol add operation.  Changes to the
+ * set of attributes for the added entry in pre-event firing will effect the
+ * result.  Meaning extra attributes and values or their deletion will be
+ * reflected in the added entry.
+ */
+public class AddEvent
+    extends ProtocolEvent
+{
+    private Name m_name ;
+	private Attributes m_attributes ;
+    private DirContext m_base ;
+
+
+    public AddEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, ADDREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    public DirContext getBase()
+    {
+        return m_base ;
+    }
+
+
+    public void setBase(DirContext a_base)
+    {
+        m_base = a_base ;
+    }
+
+
+    public Name getName()
+    {
+        return m_name ;
+    }
+
+
+    public void setName(Name a_name)
+    {
+        m_name = a_name ;
+    }
+
+
+    public Attributes getAttributes()
+    {
+        return m_attributes ;
+    }
+
+
+    public void setAttributes(Attributes a_attribute)
+    {
+        m_attributes = a_attribute ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/BindEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/BindEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,164 @@
+/*
+ * $Id: BindEvent.java,v 1.3 2003/03/13 18:27:25 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.Name ;
+import java.security.Principal;
+
+
+/**
+ * Event which logically represents a protocol bind operation.  Some properties
+ * of this event will only be present after the bind operation has completed.
+ * Changes to already initialized mutable event properties are not possible
+ * after.
+ */
+public class BindEvent
+    extends ProtocolEvent
+{
+    private Name m_dn ;
+    private Boolean isSimple = null ;
+	private Principal m_principal = null ;
+
+
+    /**
+     * Minimally creates a BindEvent without populating it with the information
+     * required to fire the event.
+     */
+    public BindEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, BINDREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Gets the unnormalized distinguished name of the user trying to bind.
+     * This parameter is available on both before and after event firings.
+     *
+     * @return the unnormalized distinguished name of the user
+     */
+    public Name getName()
+    {
+        if(null == m_dn) {
+            throw new IllegalStateException("BindEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_dn ;
+    }
+
+
+    /**
+     * Sets the unnormalized distinguished name of the user trying to bind.
+     * This parameter is available on both before and after event firings.
+     *
+     * @param a_dn the unnormalized distinguished name of the user
+     */
+    public void setName(Name a_dn)
+    {
+        if(null == m_dn) {
+        	m_dn = a_dn ;
+        } else {
+            throw new IllegalStateException("Name change via setName() "
+                + "after propertiy initialization not allowed.  setName() can "
+                + "be called at most once.") ;
+        }
+    }
+
+
+    /**
+     * Checks to see if the authentication method is simple.  This event
+     * property is available on both before and after event firings.
+     *
+     * @return true if the authentication method is simple, false if it is SASL
+     */
+    public boolean isSimple()
+    {
+        if(null == isSimple) {
+            throw new IllegalStateException("BindEvent has not been properly "
+                + "initialized!") ;
+        }
+
+		return isSimple.booleanValue() ;
+    }
+
+
+    /**
+     * Checks to see if the authentication method is simple.  This event
+     * property is available on both before and after event firings.
+     *
+     * @return true if the authentication method is simple, false if it is SASL
+     */
+    public boolean getSimple()
+    {
+        if(null == isSimple) {
+            throw new IllegalStateException("BindEvent has not been properly "
+                + "initialized!") ;
+        }
+
+		return isSimple.booleanValue() ;
+    }
+
+
+    /**
+     * Checks to see if the authentication method is simple.  This event
+     * property is available on both before and after event firings.
+     *
+     * @param isSimple true if the authentication method is simple, false if it
+     * is SASL
+     */
+    public void setSimple(boolean isSimple)
+    {
+        if(null == this.isSimple) {
+        	this.isSimple = new Boolean(isSimple) ;
+        } else {
+            throw new IllegalStateException("Name change via setSimple() "
+                + "after propertiy initialization not allowed.  setName() can "
+                + "be called at most once.") ;
+        }
+    }
+
+
+    /**
+     * Gets the user principal that has just bound a session with the server.
+     * This event property is only available after the bind operation and can
+     * only be set once.
+     *
+     * @return the authenticated user.
+     */
+    public Principal getPrincipal()
+    {
+        if(null == m_principal) {
+            throw new IllegalStateException("BindEvent has not been properly "
+                + "initialized!\nThis will be the case if this property is "
+                + "accessed before the operation has occurred.") ;
+        }
+
+		return m_principal ;
+    }
+
+
+    /**
+     * Sets the user principal that has just bound a session with the server.
+     * This event property is only available after the bind operation.
+     *
+     * @param a_principal the authenticated user.
+     */
+    public void setPrincipal(Principal a_principal)
+    {
+        if(null == m_principal) {
+        	m_principal = a_principal ;
+        } else {
+            throw new IllegalStateException("Prinicipal change via "
+                + "setPrincipal() after propertiy initialization not allowed. "
+                + "\nsetPrincipal() can be called at most once.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/CompareEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/CompareEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,179 @@
+/*
+ * $Id: CompareEvent.java,v 1.3 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.directory.Attributes ;
+
+
+/**
+ * Event which logically represents a protocol compare operation.  The events
+ * properties are all initialized for both the before and after event firings
+ * available to both event listener methods.  Alteration attempts to event
+ * properties result in a IllegalStateException since they can only be set once.
+ */
+public class CompareEvent
+    extends ProtocolEvent
+{
+    /** The Dn of the entry compared */
+	private Name m_dn = null ;
+    /** The attributes in the entry whose values are compared. */
+	private Attributes m_attributes = null ;
+    /** The name of the attribute to compare */
+    private String m_attrId = null ;
+    /** The value to use in the attribute comparison */
+    private Object m_attrValue = null ;
+
+
+    /**
+     * Creates a baseline uninitialized ComareEvent.
+     *
+     * @param a_src the source of the event.
+     * @param a_isPduDelivered whether or not an actual physical compare pdu
+     * caused this event.
+     */
+    public CompareEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, COMPAREREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Sets the distinguished name of entry to compare.
+     *
+     * @param a_dn the distinguished name of the entry to compare.
+     */
+    public void setName(Name a_dn)
+    {
+        if(null == m_dn) {
+	        m_dn = a_dn ;
+        } else {
+            throw new IllegalStateException("Can't call setName() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the distinguished name of the entry to compare.
+     *
+     * @return the dn of the entry to compare.
+     */
+    public Name getName()
+    {
+        if(null == m_dn) {
+            throw new IllegalStateException("CompareEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_dn ;
+    }
+
+
+	/**
+     * Gets the Attributes of the entry is about to be compared.
+     * This property is available for both before and after operations event
+     * firings.
+     *
+     * @return the entry Attributes
+     */
+    public Attributes getAttributes()
+    {
+        if(null == m_attributes) {
+            throw new IllegalStateException("CompareEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_attributes ;
+    }
+
+
+    /**
+     * Sets the events attributes for the entry that is about to or already has
+     * been compared by the server.  This property is available for both before
+     * and after operation event firings.
+     * 
+     * @param a_attributes the attributes for the compared entry.
+     */
+	public void setAttributes(Attributes a_attributes)
+    {
+        if(null == m_attributes) {
+	        m_attributes = a_attributes ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+
+
+    /**
+     * Gets the value of the attribute to use in this comparison.
+     *
+     * @return the value of the attribute to compare with the entry.
+     */
+	public Object getAttributeValue()
+    {
+        if(null == m_attrValue) {
+            throw new IllegalStateException("CompareEvent has not been properly"
+                + " initialized!") ;
+        }
+
+        return this.m_attrValue ;
+    }
+
+
+    /**
+     * Gets the name or Id of the attribute used in this comparison.
+     *
+     * @return the name or id of the comparison attribute.
+     */
+    public String getAttributeId()
+    {
+        if(null == m_attrId) {
+            throw new IllegalStateException("CompareEvent has not been properly"
+                + " initialized!") ;
+        }
+
+        return this.m_attrId ;
+    }
+
+
+    /**
+     * Sets the value of the attribute to use in this comparison.
+     *
+     * @param a_value the value of the attribute to compare with the entry.
+     */
+	public void setAttributeValue(Object a_value)
+    {
+        if(null == m_attrValue) {
+	        m_attrValue = a_value ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+
+
+    /**
+     * Sets the name or Id of the attribute used in this comparison.
+     *
+     * @return the name or id of the comparison attribute.
+     */
+    public void setAttributeId(String a_attrId)
+    {
+        if(null == m_attrId) {
+	        m_attrId = a_attrId ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/DelEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/DelEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,109 @@
+/*
+ * $Id: DelEvent.java,v 1.3 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.directory.Attributes ;
+
+
+/**
+ * Event which logically represents a protocol del operation.
+ */
+public class DelEvent
+    extends ProtocolEvent
+{
+    /** The distinguished name of the entry to remove. */
+    private Name m_dn = null ;
+    /** The attributes of the entry to remove */
+    private Attributes m_attributes = null ;
+
+
+    /**
+     * Creates an uninitialized DelEvent.
+     *
+     * @param a_src the source of the event.
+     * @param a_isPduDelivered true if this event represents a physical PDU
+     * delivery or is a logical representation of the operation through the
+     * JNDI provider.
+     */
+    public DelEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, DELREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Sets the distinguished name of entry to remove.
+     *
+     * @param a_dn the distinguished name of the entry to remove.
+     */
+    public void setName(Name a_dn)
+    {
+        if(null == m_dn) {
+	        m_dn = a_dn ;
+        } else {
+            throw new IllegalStateException("Can't call setName() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the distinguished name of the entry to remove.
+     *
+     * @return the dn of the entry to remove.
+     */
+    public Name getName()
+    {
+        if(null == m_dn) {
+            throw new IllegalStateException("DelEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_dn ;
+    }
+
+
+	/**
+     * Gets the Attributes of the entry is about to be removed or was removed.
+     * This property is available for both before and after operations event
+     * firings.
+     *
+     * @return the entry Attributes
+     */
+    public Attributes getAttributes()
+    {
+        if(null == m_attributes) {
+            throw new IllegalStateException("DelEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_attributes ;
+    }
+
+
+    /**
+     * Sets the events attributes for the entry that is about to or already has
+     * been deleted from the server.  This property is available for both before
+     * and after operations event firings.
+     * 
+     * @param a_attributes the attributes for the deleted entry.
+     */
+	public void setAttributes(Attributes a_attributes)
+    {
+        if(null == m_attributes) {
+	        m_attributes = a_attributes ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,65 @@
+/*
+ * $Id: EventManager.java,v 1.3 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+/**
+ * The service interface for a synchronous protocol event manager.
+ */
+public interface EventManager
+{
+    /** The ROLE is the fully qualified name of this interface */
+    public static final String ROLE = EventManager.class.getName() ;
+
+	/**
+     * Synchronously fires a protocol event calling the event handler of all
+     * registered listeners for the event type of a_event after the operatation
+     * successfully takes place.
+     *
+     * @param a_event the event to fire after the operation
+     */
+    void fireAfter(ProtocolEvent a_event) ;
+
+	/**
+     * Synchronously fires a protocol event calling the event handler of all
+     * registered listeners for the event type of a_event before the operatation
+     * takes place.
+     *
+     * @param a_event the event to fire before the operation
+     */
+    void fireBefore(ProtocolEvent a_event) ;
+
+    /**
+     * Checks to see if a listener is registered for event delivery of this
+     * kind specified by a_mask.
+     */
+    boolean hasListener(int a_mask) ;
+
+    /**
+     * Adds a protocol event listener registering it for events that would be
+     * accepted by a_mask.
+     *
+     * @param a_listener the protocol listener to register.
+     * @param a_mask used to determine which events the listener will recieve.
+     */
+    void addListener(ProtocolListener a_listener, int a_mask) ;
+
+    /**
+     * Adds a protocol event listener registering it for events that would be
+     * accepted by a_mask.
+     *
+     * @param a_listener the protocol listener to register.
+     * @param a_mask used to determine which events the listener will recieve.
+     * @param whether or not errors in a_listener's event handler are trapped,
+     * trapped errors cannot effect the outcome of the operation.
+     */
+    void addListener(ProtocolListener a_listener, int a_mask,
+        boolean trapErrors) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/EventModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,327 @@
+/*
+ * $Id: EventModule.java,v 1.5 2003/03/13 18:27:26 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import java.util.HashMap ;
+import java.util.Iterator ;
+
+import org.apache.eve.AbstractModule ;
+
+import org.apache.avalon.framework.configuration.Configuration ;
+
+
+/**
+ * Default synchronous event manager implementation for the server.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.event.protocol.EventManager"
+ * @phoenix:mx-topic name="backend-nexus"
+ */
+public class EventModule
+    extends AbstractModule
+    implements EventManager
+{
+    /** Map of listeners to their Listener spec. */
+	private HashMap m_listeners = new HashMap() ;
+    /**
+     * Current mask used to determine if an event listener of a specific type
+     * is registered to recieve events.  This mask is constructed by doing a
+     * comulative bitwise OR on it and the registered event masks of a listener.
+     */
+    private int m_mask = 0 ;
+
+
+    /**
+     * Adds a protocol event listener registering it for events that would be
+     * accepted by a_mask.
+     *
+     * @param a_listener the protocol listener to register.
+     * @param a_mask used to determine which events the listener will recieve.
+     * @param whether or not errors in a_listener's event handler are trapped,
+     * trapped errors cannot effect the outcome of the operation.
+     */
+    public void addListener(ProtocolListener a_listener, int a_mask,
+        boolean trapErrors)
+    {
+		if(!ProtocolEvent.isValid(a_mask)) {
+			throw new IllegalArgumentException("Invalid mask parameter.") ;
+        }
+
+		ListenerSpec l_spec = new ListenerSpec() ;
+		l_spec.mask = a_mask ;
+		l_spec.trapErrors = trapErrors ;
+
+        synchronized(m_listeners) {
+            m_listeners.put(a_listener, l_spec) ;
+            m_mask |= a_mask ; 
+        }
+    }
+
+
+    /**
+     * Adds a protocol event listener registering it for events that would be
+     * accepted by a_mask.
+     *
+     * @param a_listener the protocol listener to register.
+     * @param a_mask used to determine which events the listener will recieve.
+     */
+    public void addListener(ProtocolListener a_listener, int a_mask)
+    {
+		if(!ProtocolEvent.isValid(a_mask)) {
+			throw new IllegalArgumentException("Invalid mask parameter.") ;
+        }
+
+		ListenerSpec l_spec = new ListenerSpec() ;
+		l_spec.mask = a_mask ;
+
+        synchronized(m_listeners) {
+            m_listeners.put(a_listener, l_spec) ;
+            m_mask |= a_mask ; 
+        }
+    }
+
+
+    public boolean hasListener(int a_mask)
+    {
+        return (m_mask & a_mask) == a_mask ;
+    }
+
+
+	/**
+     * Synchronously fires a protocol event calling the event handler of all
+     * registered listeners for the event type of a_event after the operatation
+     * successfully takes place.
+     *
+     * @param a_event the event to fire after the operation
+     */
+    public void fireAfter(ProtocolEvent a_event)
+    {
+		Iterator l_list = m_listeners.keySet().iterator() ;
+		while(l_list.hasNext()) {
+			ProtocolListener l_listener = (ProtocolListener) l_list.next() ;
+			ListenerSpec l_spec = (ListenerSpec)
+				m_listeners.get(l_listener) ;
+
+			// If the listener is registered for the a_event type
+			if(a_event.accepts(l_spec.mask)) {
+				if(l_spec.trapErrors) {
+					try {
+						afterOn(l_listener, a_event) ;
+					} catch(Throwable t) {
+						super.getLogger().error("Listener " + l_listener
+							+ " failed to successfully handle event "
+							+ a_event) ;
+					}
+				} else {
+					try {
+						afterOn(l_listener, a_event) ;
+					} catch(RuntimeException re) {
+						throw re ;
+					}
+				}
+			}
+        }
+    }
+
+
+	/**
+     * Synchronously fires a protocol event calling the event handler of all
+     * registered listeners for the event type of a_event before the operatation
+     * takes place.
+     *
+     * @param a_event the event to fire before the operation
+     */
+    public void fireBefore(ProtocolEvent a_event)
+    {
+		Iterator l_list = m_listeners.keySet().iterator() ;
+		while(l_list.hasNext()) {
+			ProtocolListener l_listener = (ProtocolListener) l_list.next() ;
+			ListenerSpec l_spec = (ListenerSpec)
+				m_listeners.get(l_listener) ;
+
+			// If the listener is registered for the a_event type
+			if(a_event.accepts(l_spec.mask)) {
+				if(l_spec.trapErrors) {
+					try {
+						beforeOn(l_listener, a_event) ;
+					} catch(Throwable t) {
+						super.getLogger().error("Listener " + l_listener
+							+ " failed to successfully handle event "
+							+ a_event) ;
+					}
+				} else {
+					try {
+						beforeOn(l_listener, a_event) ;
+					} catch(RuntimeException re) {
+						throw re ;
+					}
+				}
+			}
+		}
+    }
+
+
+    /**
+     * Calls the after() method on a_listener using a_event as the argument
+     * using a switch on the event mask to cast the event to the appropriate
+     * event class type.
+     * 
+     * @param a_listener to call the after method on
+     * @param a_event the protocol event to use when calling after()
+     */
+    private void afterOn(ProtocolListener a_listener, ProtocolEvent a_event)
+    {
+        switch(a_event.mask) {
+        case(ProtocolEvent.ABANDONREQUEST_MASK):
+            a_listener.after((AbandonEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.ADDREQUEST_MASK):
+            a_listener.after((AddEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.BINDREQUEST_MASK):
+            a_listener.after((BindEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.COMPAREREQUEST_MASK):
+            a_listener.after((CompareEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.DELREQUEST_MASK):
+            a_listener.after((DelEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.EXTENDEDREQ_MASK):
+            a_listener.after((ExtendedEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.MODDNREQUEST_MASK):
+            a_listener.after((ModifyDnEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.MODIFYREQUEST_MASK):
+            a_listener.after((ModifyEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.SEARCHREQUEST_MASK):
+            a_listener.after((SearchEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.UNBINDREQUEST_MASK):
+            a_listener.after((UnbindEvent) a_event) ;
+            break ;
+		default:
+            throw new IllegalArgumentException("Unidentified event mask type "
+            + a_event.mask) ;
+        }
+    }
+
+
+    /**
+     * Calls the before() method on a_listener using a_event as the argument
+     * using a switch on the event mask to cast the event to the appropriate
+     * event class type.
+     *
+     * @param a_listener to call the before method on
+     * @param a_event the protocol event to use when calling before()
+     */
+    private void beforeOn(ProtocolListener a_listener, ProtocolEvent a_event)
+    {
+        switch(a_event.mask) {
+        case(ProtocolEvent.ABANDONREQUEST_MASK):
+            a_listener.before((AbandonEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.ADDREQUEST_MASK):
+            a_listener.before((AddEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.BINDREQUEST_MASK):
+            a_listener.before((BindEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.COMPAREREQUEST_MASK):
+            a_listener.before((CompareEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.DELREQUEST_MASK):
+            a_listener.before((DelEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.EXTENDEDREQ_MASK):
+            a_listener.before((ExtendedEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.MODDNREQUEST_MASK):
+            a_listener.before((ModifyDnEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.MODIFYREQUEST_MASK):
+            a_listener.before((ModifyEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.SEARCHREQUEST_MASK):
+            a_listener.before((SearchEvent) a_event) ;
+            break ;
+        case(ProtocolEvent.UNBINDREQUEST_MASK):
+            a_listener.before((UnbindEvent) a_event) ;
+            break ;
+		default:
+            throw new IllegalArgumentException("Unidentified event mask type "
+            + a_event.mask) ;
+        }
+    }
+
+
+    /** Crap */
+    class ListenerSpec {
+        int mask = 0 ;
+        boolean trapErrors = false ;
+    }
+
+
+    ////////////////////
+    // Module Methods //
+    ////////////////////
+
+
+    /**
+     * Gets the service interface (a.k.a ROLE) used by this module.
+     *
+     * @return the ROLE of this module.
+     */
+	public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets a descriptive name for this module.
+     *
+     * @return the descriptive name for this module.
+     */
+    public String getImplementationName()
+    {
+        return "Protocol Event Module" ;
+    }
+
+
+    /**
+     * Gets the implementing class name of this module.
+     *
+     * @return the name of this module's class.
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    //////////////////////////////
+    // Avalon Lifecycle Methods //
+    //////////////////////////////
+
+
+    /**
+     * Module configuration life-cycle method.
+     *
+     * @param a_config the block level configuration for this module
+     */
+    public void configure(Configuration a_config)
+    {
+        // Does nothing ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ExtendedEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ExtendedEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,104 @@
+/*
+ * $Id: ExtendedEvent.java,v 1.3 2003/03/13 18:27:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import java.util.EventObject ;
+
+
+/**
+ * Event which logically represents a protocol extended operation.
+ */
+public class ExtendedEvent
+    extends ProtocolEvent
+{
+    /** The OID of the extended operation */
+	private String m_oid = null ;
+    /** The binary payload of the extended request */
+    private byte [] m_payload = null ;
+
+
+    /**
+     * Creates an uninitialized ExtendedEvent.
+     * 
+     * @param a_src the source of the event.
+     * @param a_isPduDelivered true if this event represents a physical PDU
+     * delivery or is a logical representation of the operation through the
+     * JNDI provider.
+     */
+    public ExtendedEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, EXTENDEDREQ_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Gets the extended operation's Oid.
+     *
+     * @return the OID of the extended operation.
+     */
+	public String getOid()
+    {
+        if(null == m_oid) {
+            throw new IllegalStateException("ExtendedEvent has not been "
+                + "properly initialized!") ;
+        }
+
+        return m_oid ;
+    }
+
+
+    /**
+     * Sets the extended operation's Oid.
+     *
+     * @param a_oid the OID of the extended operation.
+     */
+	public void setOid(String a_oid)
+    {
+        if(null == m_oid) {
+        	m_oid = a_oid ;
+        } else {
+            throw new IllegalStateException("Can't call setOid() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the payload of the extended operation.
+     *
+     * @return the payload of the extended request
+     */
+    public byte [] getPayload()
+    {
+        if(null == m_payload) {
+            throw new IllegalStateException("ExtendedEvent has not been "
+                + "properly initialized!") ;
+        }
+
+        return m_payload ;
+    }
+
+
+    /**
+     * Sets the payload of the extended operation.
+     *
+     * @param a_payload the payload of the extended request
+     */
+    public void setPayload(byte [] a_payload)
+    {
+        if(null == m_payload) {
+	        m_payload = a_payload ;
+        } else {
+            throw new IllegalStateException("Can't call setPayload() more than "
+                + "once!") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyDnEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyDnEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,174 @@
+/*
+ * $Id: ModifyDnEvent.java,v 1.3 2003/03/13 18:27:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import java.util.EventObject ;
+import javax.naming.Name;
+import javax.naming.directory.Attributes;
+
+
+/**
+ * Event which logically represents a protocol modifyDn operation.
+ */
+public class ModifyDnEvent
+    extends ProtocolEvent
+{
+    /** The distinguished name of the entry modified. */
+	private Name m_dn = null ;
+    /** The new relative distinguished name of the entry modified. */
+	private Name m_rdn = null ;
+    /** The new base distinguished name of the entry to be moved. */
+	private Name m_newBase = null ;
+    /** The attributes of the entry being modified. */
+    private Attributes m_attributes = null ;
+
+
+    /**
+     * Creates an uninitialized ModifyDnEvent.
+     */
+    public ModifyDnEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, MODDNREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Sets the distinguished name of entry to move.
+     *
+     * @param a_dn the distinguished name of the entry to move.
+     */
+    public void setName(Name a_dn)
+    {
+        if(null == m_dn) {
+	        m_dn = a_dn ;
+        } else {
+            throw new IllegalStateException("Can't call setName() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the distinguished name of the entry to change the dn of.
+     *
+     * @return the dn of the entry to move.
+     */
+    public Name getName()
+    {
+        if(null == m_dn) {
+            throw new IllegalStateException("ModifyDnEvent has not been"
+                + "properly initialized!") ;
+        }
+
+        return m_dn ;
+    }
+
+
+    /**
+     * Sets the new relative name of entry to move.
+     *
+     * @param a_rdn the relative name of the entry to move.
+     */
+    public void setRdn(Name a_rdn)
+    {
+        if(null == m_rdn) {
+	        m_rdn = a_rdn ;
+        } else {
+            throw new IllegalStateException("Can't call setRdn() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the relative name of the entry to change the dn of.
+     *
+     * @return the rdn of the entry to move.
+     */
+    public Name getRdn()
+    {
+        if(null == m_rdn) {
+            throw new IllegalStateException("ModifyDnEvent has not been"
+                + "properly initialized!") ;
+        }
+
+        return m_rdn ;
+    }
+
+
+    /**
+     * Sets the distinguished name of entry to move.
+     *
+     * @param a_newBase the distinguished name of the entry to move.
+     */
+    public void setBaseName(Name a_newBase)
+    {
+        if(null == m_dn) {
+	        m_newBase = a_newBase ;
+        } else {
+            throw new IllegalStateException("Can't call setBaseName() more than"
+                + " once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the new base distinguished name of the entry to move the entry
+     * under.
+     *
+     * @return the base dn to move the entry to.
+     */
+    public Name getBaseName()
+    {
+        if(null == m_newBase) {
+            throw new IllegalStateException("ModifyDnEvent has not been"
+                + "properly initialized!") ;
+        }
+
+        return m_newBase ;
+    }
+
+
+	/**
+     * Gets the Attributes of the entry is about to have its DN modified.
+     * This property is available for both before and after operations event
+     * firings.
+     *
+     * @return the entry Attributes
+     */
+    public Attributes getAttributes()
+    {
+        if(null == m_attributes) {
+            throw new IllegalStateException("ModifyDnEvent has not been"
+                + "properly initialized!") ;
+        }
+
+        return m_attributes ;
+    }
+
+
+    /**
+     * Sets the events attributes for the entry that is about to or already has
+     * been modified by the server.  This property is available for both before
+     * and after operations event firings.
+     * 
+     * @param a_attributes the attributes for the modified entry.
+     */
+	public void setAttributes(Attributes a_attributes)
+    {
+        if(null == m_attributes) {
+	        m_attributes = a_attributes ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ModifyEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,148 @@
+/*
+ * $Id: ModifyEvent.java,v 1.3 2003/03/13 18:27:28 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.directory.Attributes ;
+import javax.naming.directory.ModificationItem ;
+
+
+/**
+ * Event which logically represents a protocol modify operation.
+ */
+public class ModifyEvent
+    extends ProtocolEvent
+{
+    /** The distinguished name of the entry to modify. */
+    private Name m_dn = null ;
+    /** The attributes of the entry to modify */
+    private Attributes m_attributes = null ;
+	/** The modifications made or to be made on the entry */
+    private ModificationItem [] m_mods = null ;
+
+
+    /**
+     * Creates an uninitialized ModifyEvent.
+     *
+     * @param a_src the source of the event.
+     * @param a_isPduDelivered true if this event represents a physical PDU
+     * delivery or is a logical representation of the operation through the
+     * JNDI provider.
+     */
+    public ModifyEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, MODIFYREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Sets the distinguished name of entry to modified.
+     *
+     * @param a_dn the distinguished name of the entry to modified.
+     */
+    public void setName(Name a_dn)
+    {
+        if(null == m_dn) {
+	        m_dn = a_dn ;
+        } else {
+            throw new IllegalStateException("Can't call setName() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the distinguished name of the entry to modified.
+     *
+     * @return the dn of the entry to remove.
+     */
+    public Name getName()
+    {
+        if(null == m_dn) {
+            throw new IllegalStateException("ModifyEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_dn ;
+    }
+
+
+	/**
+     * Gets the Attributes of the entry is about to be modified or was modified.
+     * This property is available for both before and after operations event
+     * firings.
+     *
+     * @return the entry Attributes
+     */
+    public Attributes getAttributes()
+    {
+        if(null == m_attributes) {
+            throw new IllegalStateException("ModifyEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_attributes ;
+    }
+
+
+    /**
+     * Sets the events attributes for the entry that is about to or already has
+     * been modified by the server.  This property is available for both before
+     * and after operations event firings.
+     * 
+     * @param a_attributes the attributes for the modified entry.
+     */
+	public void setAttributes(Attributes a_attributes)
+    {
+        if(null == m_attributes) {
+	        m_attributes = a_attributes ;
+        } else {
+            throw new IllegalStateException("The attributes of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+
+
+	/**
+     * Gets the Modifications on the entry that is about to be modified or was
+     * modified.  This property is available for both before and after
+     * operations event firings.
+     *
+     * @return the entry ModificationItems
+     */
+    public ModificationItem [] getModifications()
+    {
+        if(null == m_mods) {
+            throw new IllegalStateException("ModifyEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_mods ;
+    }
+
+
+    /**
+     * Sets the event's modifications on the entry that is about to or already
+     * has been modified by the server.  This property is available for both
+     * before and after operations event firings.
+     * 
+     * @param a_mods the attributes for the modified entry.
+     */
+	public void setModifications(ModificationItem [] a_mods)
+    {
+        if(null == m_mods) {
+	        m_mods = a_mods ;
+        } else {
+            throw new IllegalStateException("The modification of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolAdapter.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolAdapter.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,55 @@
+/*
+ * $Id: ProtocolAdapter.java,v 1.2 2003/03/13 18:27:28 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+public class ProtocolAdapter
+	implements ProtocolListener
+{
+    public void after(UnbindEvent a_event) { }
+
+    public void after(SearchEvent a_event) { }
+
+    public void after(ModifyDnEvent a_event) { }
+
+    public void after(ModifyEvent a_event) { }
+
+    public void after(ExtendedEvent a_event) { }
+
+    public void after(DelEvent a_event) { }
+
+    public void after(CompareEvent a_event) { }
+
+    public void after(BindEvent a_event) { }
+
+    public void after(AddEvent a_event) { }
+
+    public void after(AbandonEvent a_event) { }
+
+	public void before(UnbindEvent a_event) { }
+
+	public void before(SearchEvent a_event) { }
+
+	public void before(ModifyDnEvent a_event) { }
+
+	public void before(ModifyEvent a_event) { }
+
+	public void before(ExtendedEvent a_event) { }
+
+	public void before(DelEvent a_event) { }
+
+	public void before(CompareEvent a_event) { }
+
+	public void before(BindEvent a_event) { }
+
+	public void before(AddEvent a_event) { }
+
+	public void before(AbandonEvent a_event) { }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,188 @@
+/*
+ * $Id: ProtocolEvent.java,v 1.3 2003/03/13 18:27:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import java.util.EventObject ;
+
+
+/**
+ * Event which logically represents a protocol unbind operation.
+ */
+public class ProtocolEvent
+    extends EventObject
+{
+    /** Bind request type mask */
+  	public static final int BINDREQUEST_MASK	= 0x40000000 ;
+    /** Unbind request type mask */
+  	public static final int UNBINDREQUEST_MASK	= 0x40000002 ;
+    /** Search request type mask */
+  	public static final int SEARCHREQUEST_MASK	= 0x40000003 ;
+    /** Modify request type mask */
+  	public static final int MODIFYREQUEST_MASK	= 0x40000006 ;
+    /** Add request type mask */
+  	public static final int ADDREQUEST_MASK		= 0x40000008 ;
+    /** Del request type mask */
+  	public static final int DELREQUEST_MASK		= 0x4000000a ;
+    /** Modify Dn request type mask */
+  	public static final int MODDNREQUEST_MASK	= 0x4000000c ;
+    /** Compare request type mask */
+  	public static final int COMPAREREQUEST_MASK	= 0x4000000e ;
+    /** Abandon request type mask */
+  	public static final int ABANDONREQUEST_MASK	= 0x40000010 ;
+    /** Extended request type mask */
+  	public static final int EXTENDEDREQ_MASK	= 0x40000017 ;
+
+	/** A [] of all the event type masks */
+  	private final static int list[] = { BINDREQUEST_MASK, UNBINDREQUEST_MASK,
+        SEARCHREQUEST_MASK, MODIFYREQUEST_MASK, ADDREQUEST_MASK,
+        DELREQUEST_MASK, MODDNREQUEST_MASK, COMPAREREQUEST_MASK,
+        ABANDONREQUEST_MASK, EXTENDEDREQ_MASK } ;
+
+  	/**
+     * A super mask accepting any event generated by bitwise ORing all the
+     * defined event mask's.  This mask will always return true on calls to
+     * accepts regardless of the event type.
+     */
+  	public static final int ALL_MASK =
+        ABANDONREQUEST_MASK | ADDREQUEST_MASK   | BINDREQUEST_MASK   |
+        COMPAREREQUEST_MASK | DELREQUEST_MASK   | EXTENDEDREQ_MASK   |
+        MODDNREQUEST_MASK   | MODDNREQUEST_MASK | SEARCHREQUEST_MASK |
+        UNBINDREQUEST_MASK ;
+
+
+    /**
+     * Checks to see if a mask is composed of valid mask event values.
+     *
+     * @param mask the mask value to verify.
+     * @return true if the mask is composed of valid event mask values, false
+     * otherwise.
+     */
+    public static boolean isValid(int mask)
+    {
+        return (ALL_MASK & mask) == mask ;
+    }
+
+
+    /**
+     * Checks to see if a event mask type value is defined.
+     *
+     * @param mask the type mask value to verify.
+     * @throws IllegalArgumentException if the mask is not valid.
+     */
+    public static void checkEventType(int mask)
+    {
+        switch(mask) {
+        case(ABANDONREQUEST_MASK):
+            break ;
+        case(ADDREQUEST_MASK):
+            break ;
+        case(BINDREQUEST_MASK):
+            break ;
+        case(COMPAREREQUEST_MASK):
+            break ;
+        case(DELREQUEST_MASK):
+            break ;
+        case(EXTENDEDREQ_MASK):
+            break ;
+        case(MODDNREQUEST_MASK):
+            break ;
+        case(MODIFYREQUEST_MASK):
+            break ;
+        case(SEARCHREQUEST_MASK):
+            break ;
+        case(UNBINDREQUEST_MASK):
+            break ;
+        default:
+            throw new IllegalArgumentException("Could not recognize protocol "
+            	+ "event operation mask value of " + mask) ;
+    	}
+    }
+
+
+    //////////////////////
+    // Member Variables //
+    //////////////////////
+
+
+    /** The type mask for this event */
+  	public final int mask ;
+    /** Whether or not this event represents the physical delivery of a PDU */
+	public final boolean pduDelivered ;
+
+
+    /**
+     * Creates a logical protocol event representing a protocol operation.
+     *
+     * @param a_src the source triggering this event (the caller?)
+     * @param a_mask the event mask used to identify this event type.
+     * @param a_pduDelivered true if this event is to represent the delivery of
+     * a physical PDU for this protocol operation.
+     */
+    ProtocolEvent(Object a_src, int a_mask, boolean a_pduDelivered)
+    {
+		super(a_src) ;
+        mask = a_mask ;
+        pduDelivered = a_pduDelivered ;
+        checkEventType(mask) ;
+    }
+
+
+    /**
+     * Gets whether or not the actual protocol data unit request for an unbind
+     * operation was issued againts the server via the protocol handler.  If
+     * this is false the session may have been terminated due to timeout or as
+     * a result of a client server error.
+     *
+     * @return true if the actual unbind pdu was delivered, false otherwise.
+     */
+    public boolean getPduDelivered()
+    {
+        return pduDelivered ;
+    }
+
+
+    /**
+     * Gets whether or not the actual protocol data unit request for an unbind
+     * operation was issued againts the server via the protocol handler.  If
+     * this is false the session may have been terminated due to timeout or as
+     * a result of a client server error.
+     *
+     * @return true if the actual unbind pdu was delivered, false otherwise.
+     */
+    public boolean isPduDelivered()
+    {
+        return pduDelivered ;
+    }
+
+
+    /**
+     * Returns whether or not an event mask argument accepts this event
+     * type.
+     *
+     * @param a_mask the mask to test for a match against this event type.
+     * @return true if the mask matches for this event type, false otherwise.
+     */
+    public boolean accepts(int a_mask)
+    {
+		return ((mask & a_mask) == mask) ;
+    }
+
+
+    /**
+     * Gets the event mask type of this event.
+     *
+     * @return the event mask type.
+     */
+    public int getMask()
+    {
+        return mask ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/ProtocolListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,45 @@
+/*
+ * $Id: ProtocolListener.java,v 1.2 2003/03/13 18:27:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+public interface ProtocolListener
+	extends java.util.EventListener
+{
+	void before(AbandonEvent a_event) ;
+    void after(AbandonEvent a_event) ;
+
+	void before(AddEvent a_event) ;
+    void after(AddEvent a_event) ;
+
+	void before(BindEvent a_event) ;
+    void after(BindEvent a_event) ;
+
+	void before(CompareEvent a_event) ;
+    void after(CompareEvent a_event) ;
+
+	void before(DelEvent a_event) ;
+    void after(DelEvent a_event) ;
+
+	void before(ExtendedEvent a_event) ;
+    void after(ExtendedEvent a_event) ;
+
+	void before(ModifyEvent a_event) ;
+    void after(ModifyEvent a_event) ;
+
+	void before(ModifyDnEvent a_event) ;
+    void after(ModifyDnEvent a_event) ;
+
+	void before(SearchEvent a_event) ;
+    void after(SearchEvent a_event) ;
+
+	void before(UnbindEvent a_event) ;
+    void after(UnbindEvent a_event) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/SearchEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/SearchEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,143 @@
+/*
+ * $Id: SearchEvent.java,v 1.3 2003/03/13 18:27:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.directory.Attributes ;
+import javax.naming.directory.SearchControls ;
+import org.apache.ldap.common.filter.ExprNode ;
+
+
+/**
+ * Event which logically represents a protocol search operation.
+ */
+public class SearchEvent
+    extends ProtocolEvent
+{
+    /** The search base as a name */
+	private Name m_base = null ;
+    /** The search filter as an expression tree or AST */
+    private ExprNode m_filter = null ;
+    /** The attributes of the search base */
+    private Attributes m_attributes = null ;
+    /** The search controls associated with the search */
+	private SearchControls m_controls = null ;
+
+
+    /**
+     * Creates an uninitialized SearchEvent.
+     *
+     * @param a_src the source of the event.
+     * @param a_isPduDelivered true if this event represents a physical PDU
+     * delivery or is a logical representation of the operation through the
+     * JNDI provider.
+     */
+    public SearchEvent(Object a_src, boolean a_isPduDelivered)
+    {
+       super(a_src, SEARCHREQUEST_MASK, a_isPduDelivered) ;
+    }
+
+
+    /**
+     * Sets the distinguished name of search base.
+     *
+     * @param a_base the distinguished name of the search base.
+     */
+    public void setBase(Name a_base)
+    {
+        if(null == m_base) {
+	        m_base = a_base ;
+        } else {
+            throw new IllegalStateException("Can't call setBase() more than "
+                + "once!") ;
+        }
+    }
+
+
+    /**
+     * Gets the distinguished name of the search base.
+     *
+     * @return the dn of the search base.
+     */
+    public Name getBase()
+    {
+        if(null == m_base) {
+            throw new IllegalStateException("SearchEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_base ;
+    }
+
+
+    /**
+     * Gets the root ExprNode for the search filter as a AST.
+     *
+     * @return the root ExprNode
+     */
+    public ExprNode getFilter()
+    {
+        if(null == m_filter) {
+            throw new IllegalStateException("SearchEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_filter ;
+    }
+
+
+    /**
+     * Sets the root ExprNode for the search filter as a AST.
+     *
+     * @param a_filter the root ExprNode
+     */
+    public void setFilter(ExprNode a_filter)
+    {
+        if(null == m_filter) {
+			m_filter = a_filter ;
+        } else {
+            throw new IllegalStateException("The filter of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+
+
+    /**
+     * Gets the specific search controls associated with this search operation.
+     *
+     * @return the search controls for this search.
+     */
+    public SearchControls getSearchControls()
+    {
+        if(null == m_controls) {
+            throw new IllegalStateException("SearchEvent has not been properly "
+                + "initialized!") ;
+        }
+
+        return m_controls ;
+    }
+
+
+    /**
+     * Sets the specific search controls associated with this search operation.
+     *
+     * @param a_ctls the search controls associated with this search operation
+     */
+    public void setSearchControls(SearchControls a_ctls)
+    {
+        if(null == m_controls) {
+			m_controls = a_ctls ;
+        } else {
+            throw new IllegalStateException("The search controls of this event "
+                + " may only be set at most one time.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/UnbindEvent.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/event/protocol/UnbindEvent.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,23 @@
+/*
+ * $Id: UnbindEvent.java,v 1.2 2003/03/13 18:27:30 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.event.protocol ;
+
+
+/**
+ * Event which logically represents a protocol unbind operation.
+ */
+public class UnbindEvent
+    extends ProtocolEvent
+{
+    public UnbindEvent(Object a_src, boolean pduDelivered)
+    {
+       super(a_src, UNBINDREQUEST_MASK, pduDelivered) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,46 @@
+/*
+ * $Id: InputManager.java,v 1.4 2003/03/13 18:27:30 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.input ;
+
+
+import java.io.InputStream ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.client.ClientManagerSlave ;
+
+
+/**
+ * Service interface for server module that monitors incomming PDU requests on
+ * a single client InputStream.  Only one stream per client can be registered
+ * for input detection.  This service pervents a cyclic component dependency by
+ * extending the ClientManagerSlave interface.
+ */
+public interface InputManager
+    extends ClientManagerSlave
+{
+    /** Role played by this service as specified by Avalon */
+    public static final String ROLE = InputManager.class.getName() ;
+
+    /**
+     * Registers a client with this module so that input detection can occur.
+     *
+     * @param a_clientKey the unique key identifing a client
+     * @param a_clientIn the client InputStream to be monitored.
+     */
+    void register(ClientKey a_clientKey, InputStream a_clientIn) ;
+
+    /**
+     * Unregisters a client with this module so that input detection is not
+     * enabled for a client's InputStream previously enabled via the register
+     * method of this service.
+     *
+     * @param a_clientKey the unique key identifing a client
+     */
+    void unregister(ClientKey a_clientKey) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/input/InputModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,260 @@
+/*
+ * $Id: InputModule.java,v 1.7 2003/03/24 13:22:29 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.input ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+
+import java.io.InputStream ;
+import java.io.IOException ;
+import java.io.PushbackInputStream ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.decoder.Decoder ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.event.InputEvent ;
+import org.apache.eve.client.ClientManager ;
+
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.cornerstone.services.threads.ThreadManager ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+import org.apache.eve.client.KeyExpiryException;
+import org.apache.avalon.framework.logger.Logger;
+
+
+
+
+
+/**
+ * The InputModule implements the InputManager service interface and in
+ * doing so is responsible for detecting input on the client Socket's
+ * InputStream.
+ *
+ * @phoenix:block
+ * @phoenix:mx-topic name="InputModule"
+ * @phoenix:service name="org.apache.eve.input.InputManager"
+ */
+public class InputModule
+    extends AbstractModule
+    implements InputManager
+{
+    /** name of the socket listener pool used for this module: 'client' */
+    public static final String SOCKETLISTENER_POOL = "client" ;
+
+    /** forward map of ClientKeys to client InputStreams */
+    private Map m_streams = new HashMap() ;
+    /** handle on the ClientManager service */
+    private ClientManager m_clientManager = null ;
+    /** handle on the ThreadManager service */
+    private ThreadManager m_threadManager = null ;
+    /** handle on the Decoder service */
+    private Decoder m_decoder = null ;
+
+
+    /**
+     * Registers a client with this module so that input detection can occur.
+     *
+     * @param a_clientKey the unique key identifing a client
+     * @param a_clientIn the client InputStream to be monitored.
+     */
+    public synchronized
+        void register(final ClientKey a_clientKey, final InputStream a_clientIn)
+    {
+        m_streams.put(a_clientKey, a_clientIn) ;
+        Runnable l_monitor = new InputStreamMonitor(a_clientKey, a_clientIn) ;
+        m_threadManager.getThreadPool(SOCKETLISTENER_POOL).execute(l_monitor) ;
+    }
+
+
+    class InputStreamMonitor implements Runnable
+    {
+        final ClientKey m_clientKey ;
+        final InputStream m_clientIn ;
+
+        InputStreamMonitor(final ClientKey a_clientKey,
+            final InputStream a_clientIn)
+        {
+            m_clientKey = a_clientKey ;
+            m_clientIn = a_clientIn ;
+        }
+
+
+        /**
+         * Runnable implementation which monitor's a client connection for
+         * incomming LDAP request data.  The loop runs indefinately until the
+         * ClientKey expires or an IOException occurs on the clients
+         * InputStream.  IOExceptions drop client connections, log an error and
+         * request that the ClientManager drop the client if it already has not
+         * done so.
+         */
+		public void run() {
+            Logger l_log = InputModule.this.getLogger() ;
+			Object l_lock = null ;
+
+            // Obtain input lock object or return.
+            try {
+                l_lock = m_clientKey.getInputLock() ;
+            } catch(KeyExpiryException e) {
+                if(l_log.isWarnEnabled()) {
+					l_log.warn("ClientKey for " + m_clientKey + " has expired "
+                        + "immediately after server accept:", e) ;
+                }
+                return ;
+            }
+
+        	// Start input detection loop
+			try {
+				// l_in is used for the life of the connection and hence
+				// this client listener.  All InputEvents to the decoder
+				// carry this object.
+				PushbackInputStream l_in =
+					new PushbackInputStream(m_clientIn) ;
+
+				// Character is read then pushed back before event delivery
+				// so the decoder can read a complete PDU with this first byte.
+				int ch = -1 ;
+
+				synchronized(l_lock) {
+					while((ch = l_in.read()) != -1
+                        && !m_clientKey.hasExpired())
+                    {
+						l_in.unread(ch) ;
+						InputEvent l_event =
+							new InputEvent(m_clientKey, l_in) ;
+						m_decoder.inputReceived(l_event) ;
+
+						try {
+							// Wait until we are notified by event handler
+							// of the decoder to resume listening for more
+							// input from the client.  Decoder event handler
+							// needs to suck down a request message before
+							// giving us the io stream back.
+
+							l_lock.wait() ;
+						} catch(InterruptedException e) {
+							m_clientManager.drop(m_clientKey) ;
+							l_log.error("Client " + m_clientKey + " dropped on"
+                                + " InputStreamMonitor's thread error: ", e) ;
+						}
+					}
+				}
+			} catch(IOException e) {
+				m_clientManager.drop(m_clientKey) ;
+				l_log.error("Client " + m_clientKey
+                    + " dropped due to exception on read from client "
+                    + "InputStream: ", e) ;
+			}
+		}
+    }
+
+
+    /**
+     * Unregisters a client with this module so that input detection is not
+     * enabled for a client's InputStream previously enabled via the register
+     * method of this service.
+     *
+     * @param a_clientKey the unique key identifing a client
+     */
+    public synchronized void unregister(ClientKey a_clientKey)
+    {
+        m_streams.remove(a_clientKey) ;
+    }
+
+
+    /**
+     * ClientManagerSlave method implementation which prevents a cyclic
+     * dependency from this module back to the ClientManager.  This method sets
+     * the handle on the ClientManager service rather than the <code>service()
+     * </code> lifecycle method.
+     *
+     * @param a_manager the ClientManager service handle
+     */
+    public void registerClientManager(ClientManager a_manager)
+    {
+        m_clientManager = a_manager ;
+    }
+
+
+    /////////////////////////////////
+    // Module & Life-Cycle Methods //
+    /////////////////////////////////
+
+
+    /**
+     * Gets this Module implementation's descriptive name.
+     *
+     * @return descriptive module name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the descriptive name
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "Client Input Manager Module" ;
+    }
+
+
+    /**
+     * Gets this Module implementation's fully qualified class name.
+     *
+     * @return the fqcn
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the FQCN
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    /**
+     * Gets this Module implementation's service interface (a.k.a its role)
+     *
+     * @return the service interface name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the service interface (ROLE)
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets a handle on the Decoder and the ThreadManager services which this
+     * module depends on.
+     * 
+     * @phoenix:dependency name="org.apache.eve.decoder.Decoder"
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        super.service(a_manager) ;
+        m_decoder = (Decoder) a_manager.lookup(Decoder.ROLE) ;
+        m_threadManager = (ThreadManager) a_manager.lookup(ThreadManager.ROLE) ;
+    }
+
+
+    /**
+     * Does nothing.
+     *
+     * @param a_config the configuration for this module.
+     */
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/BindingEnumeration.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/BindingEnumeration.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,139 @@
+/*
+ $Id: BindingEnumeration.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ ============================================================================
+                   The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of  source code must  retain the above copyright  notice,
+    this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+    include  the following  acknowledgment:  "This product includes  software
+    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
+    Alternately, this  acknowledgment may  appear in the software itself,  if
+    and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
+    "Apache Software Foundation"  must not be used to endorse or promote
+    products derived  from this  software without  prior written
+    permission. For written permission, please contact apache@apache.org.
+
+ 5. Products  derived from this software may not  be called "Apache", nor may
+    "Apache" appear  in their name,  without prior written permission  of the
+    Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
+ APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
+ ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
+ (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software  consists of voluntary contributions made  by many individuals
+ on  behalf of the Apache Software  Foundation. For more  information on the
+ Apache Software Foundation, please see <http://www.apache.org/>.
+
+*/
+
+package org.apache.eve.jndi ;
+import javax.naming.NamingEnumeration;
+import org.apache.eve.backend.Cursor;
+import javax.naming.NamingException;
+import org.apache.eve.backend.LdapEntry;
+import javax.naming.NameClassPair;
+import org.apache.eve.backend.UnifiedBackend;
+import java.util.Hashtable;
+import org.apache.avalon.framework.ExceptionUtil;
+import javax.naming.Binding;
+
+
+public class BindingEnumeration
+    implements NamingEnumeration
+{
+    private final Hashtable m_env ;
+    private final Cursor m_cursor ;
+
+
+    BindingEnumeration( Hashtable a_env, Cursor a_cursor )
+    {
+        m_env = a_env ;
+        m_cursor = a_cursor ;
+    }
+
+
+    public void close() throws NamingException
+    {
+        m_cursor.close() ;
+    }
+
+
+    public boolean hasMore() throws NamingException
+    {
+        return m_cursor.hasMore() ;
+    }
+
+
+    public Object next() throws NamingException
+    {
+        String l_rdn = null ;
+        String l_class = null ;
+        Object l_obj = null ;
+
+        LdapEntry l_entry = ( LdapEntry ) m_cursor.next() ;
+        if( l_entry.hasAttribute( ContextHelper.JCLASSNAME_ATTR ) )
+        {
+            l_class = ( String )
+                l_entry.getSingleValue( ContextHelper.JCLASSNAME_ATTR ) ;
+            l_obj = ContextHelper.deserialize( l_entry ) ;
+        }
+        else
+		{
+            l_class = UnifiedLdapContext.class.getName() ;
+            l_obj = new UnifiedLdapContext( m_env, l_entry ) ;
+        }
+
+        l_rdn = l_entry.getNormalizedDN().get( 0 ) ;
+        return new Binding( l_rdn, l_class, l_obj ) ;
+    }
+
+
+    public boolean hasMoreElements()
+    {
+        return m_cursor.hasMoreElements() ;
+    }
+
+
+    public Object nextElement()
+    {
+        try
+        {
+            return next() ;
+        }
+        catch( NamingException e )
+        {
+            try
+            {
+                m_cursor.close() ;
+            }
+            catch( Exception e2 )
+            {
+            }
+
+            throw new java.util.NoSuchElementException( "Premature close of "
+                + "backend cursor:\n" + ExceptionUtil.printStackTrace( e ) ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ContextHelper.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ContextHelper.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,728 @@
+/*
+ * $Id: ContextHelper.java,v 1.7 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.backend.BackendException ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.NameNotFoundException ;
+
+import java.io.IOException ;
+import java.io.ObjectInputStream ;
+import java.io.ObjectOutputStream ;
+import java.io.ByteArrayInputStream ;
+import java.io.ByteArrayOutputStream ;
+import javax.naming.Context;
+import org.apache.ldap.common.util.NamespaceTools;
+import javax.naming.NamingEnumeration;
+import org.apache.eve.backend.Cursor;
+import javax.naming.OperationNotSupportedException;
+
+
+/**
+ * Contains implementation content for the UnifiedContext due to its massive
+ * size.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.7 $
+ */
+public class ContextHelper
+{
+    public static final String TOP_ATTR = "top" ;
+    public static final String JOBJECT_ATTR = "javaObject" ;
+    public static final String OBJECTCLASS_ATTR = "objectClass" ;
+    public static final String JCONTAINER_ATTR = "javaContainer" ;
+    public static final String JSERIALIZEDOBJ_ATTR = "javaSerializedObject" ;
+
+    public static final String JCLASSNAME_ATTR = "javaClassName" ;
+    public static final String JCLASSNAMES_ATTR = "javaClassNames" ;
+    public static final String JSERIALDATA_ATTR = "javaSerializedData" ;
+
+    private final UnifiedContext m_ctx ;
+
+
+
+	/**
+     * Creates a context helper for a UnifiedContext.
+     */
+    ContextHelper( UnifiedContext a_ctx )
+    {
+        m_ctx = a_ctx ;
+    }
+
+
+    public Name composeName( Name a_rdn, Name a_prefix )
+        throws NamingException
+    {
+        LdapEntry l_entry = m_ctx.getEntry() ;
+
+        // Example: This context is ou=people and say name is the relative
+        // name of uid=jwalker and the prefix is dc=domain.  Then we must
+        // compose the name relative to prefix which would be:
+        // uid=jwalker,ou=people,dc=domain.
+
+        // To do so we apply the following general algorithm.  Find this
+        // context's name relative to the prefix argument: let's call this
+        // the prefix relative name or pfn.  Construct the Name of the name
+        // argument and add to this the pfn as the suffix via a Name.addAll().
+
+        // Preliminary Step I: Return the context relative name arg if prefix
+        // is null or is an empty name.
+        if( a_prefix == null || a_prefix.size() == 0 )
+        {
+            return a_rdn ;
+        }
+
+        // Should we check to see if name arg context exists? Or do we presume
+        // that it does and handle failures on context lookups?
+
+        // Step I: Find the prn
+        // Grab last component of the prefix.  Find its position in the l_fqn.
+        // Take the prefix of l_fqn upto and including this last component.
+
+        String l_lastComp = a_prefix.get( a_prefix.size() - 1 ) ;
+        Name l_fqn = l_entry.getNormalizedDN() ;
+        Name l_prn = null ;
+        for( int ii = 0 ; ii < l_fqn.size(); ii++ )
+        {
+            if( l_fqn.get( ii ).equals( l_lastComp ) )
+            {
+                l_prn = l_fqn.getPrefix( ii + 1 ) ;
+                break ;
+            }
+        }
+
+        // Step II: Throw exception if l_prn not found which indicates that the
+        // prefix is not an ancestor of this context.
+        if( null == l_prn )
+        {
+            throw new NamingException( "The prefix '" + a_prefix+ "' is not an"
+                + " ancestor of this context '" + l_fqn + "'" ) ;
+        }
+
+        // Step III: Compose the name
+        Name l_retval = new LdapName() ;
+        l_retval.addAll( a_rdn ) ;
+        l_retval.addAll( l_prn ) ;
+        return l_retval ;
+    }
+
+
+    public String composeName( String a_rdn, String a_prefix )
+	    throws NamingException
+    {
+        if( a_prefix == null || a_prefix.trim().equals( "" ) )
+        {
+            return a_rdn ;
+        }
+
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return composeName( l_nexus.getNormalizedName( a_rdn ),
+            l_nexus.getNormalizedName( a_prefix ) ).toString() ;
+    }
+
+
+    public Object lookup( Name a_rdn ) throws NamingException
+    {
+        if( a_rdn.size() == 0 )
+        {
+            return m_ctx.clone() ;
+        }
+
+        Name l_dn = ( Name ) a_rdn.clone() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+		UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+
+        try
+        {
+            if( l_nexus.hasEntry( l_dn ) )
+            {
+                LdapEntry l_target = l_nexus.read( l_dn ) ;
+
+                if( l_target.hasAttribute( JCLASSNAME_ATTR ) )
+                {
+                    return deserialize( l_target ) ;
+                }
+
+                return new UnifiedLdapContext(
+                    m_ctx.getEnvironment(), l_target ) ;
+            }
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Nexus read('" + l_dn
+                + "') failure:\n" + e.getMessage() ) ;
+            l_ne.setRootCause( e ) ;
+        }
+
+        // JNDI NameNotFoundExceptions corresponds to LDAPv3 NOSUCHOBJECT result
+        // code with an enumeration value of [32]
+        throw new NameNotFoundException(
+            "[32] Fully qualified name '" + l_dn
+            + "' for name relative to this context of '" + a_rdn
+            + "' was not found" ) ;
+    }
+
+
+    public Object lookup( String a_rdn ) throws NamingException
+    {
+        if( null == a_rdn || a_rdn.trim().equals( "" ) )
+        {
+            return m_ctx.clone() ;
+        }
+
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return lookup( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    public void bind( Name a_rdn, Object an_obj ) throws NamingException
+    {
+        if( an_obj instanceof UnifiedLdapContext )
+        {
+            throw new IllegalArgumentException(
+                "Cannot bind a directory context object!" ) ;
+        }
+
+        Name l_dn = ( Name ) a_rdn.clone() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        LdapEntry l_newEntry = null ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+
+        try
+        {
+            l_newEntry = l_nexus.newEntry( l_dn.toString() ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed to get handle "
+                + "on an entry implementation for name '" + a_rdn+ "' due to "
+                + "nexus exception: " ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+
+        populate( l_newEntry, a_rdn, an_obj ) ;
+
+        try
+        {
+            l_nexus.create( l_newEntry ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException("Failed create entry "
+                + "for name '" + a_rdn + "' due to "
+                + "nexus exception.  Entry contains:\n" + l_newEntry ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    public void bind( String a_rdn, Object an_obj) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        bind( l_nexus.getNormalizedName( a_rdn ), an_obj ) ;
+    }
+
+
+    public void rebind( Name a_rdn, Object an_obj ) throws NamingException
+    {
+        Name l_dn = new LdapName() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            if( l_nexus.hasEntry( l_dn ) )
+            {
+                unbind( a_rdn ) ;
+            }
+
+            bind( a_rdn, an_obj ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed entry lookup "
+                + "for name '" + l_dn + "' due to nexus exception.") ;
+            l_ne.setRootCause(e) ;
+            throw l_ne ;
+        }
+    }
+
+
+    public void rebind( String a_rdn, Object an_obj ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        rebind( l_nexus.getNormalizedName( a_rdn ), an_obj ) ;
+    }
+
+
+    public void unbind( Name a_rdn ) throws NamingException
+    {
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            if( l_nexus.hasEntry( l_dn ) )
+            {
+                l_nexus.delete( l_entry ) ;
+            }
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed entry deletion "
+                + "for name '" + l_dn + "' due to nexus exception.") ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    public void unbind( String a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        unbind( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    public void rename( Name a_oldRdn, Name a_newRdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        LdapEntry l_oldEntry = null ;
+        Name l_oldDn = new LdapName() ;
+        Name l_newDn = new LdapName() ;
+        l_oldDn.addAll( l_entry.getNormalizedDN() ) ;
+        l_oldDn.addAll( a_oldRdn ) ;
+        l_newDn.addAll( l_entry.getNormalizedDN() ) ;
+        l_newDn.addAll( a_newRdn ) ;
+
+        try
+        {
+            l_oldEntry = l_nexus.read( l_oldDn ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed entry rename "
+                + "on old name '" + l_oldDn + "' to new name of '"
+                + l_newDn + "' due to a nexus read failure." ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+
+        // If both DNs are same size and their suffixes equal one another
+        // then this defaults to a simple modifyRdn operation.
+        if( l_oldDn.size() == l_newDn.size() )
+        {
+            try
+            {
+                l_nexus.modifyRdn( l_oldEntry, a_newRdn, true ) ;
+            }
+            catch( BackendException e )
+            {
+                NamingException l_ne = new NamingException( "Failed on nexus "
+                    + "modifyRdn on old name '" + l_oldDn + "' to new name '"
+                    + l_newDn + "' due to a backend failure." ) ;
+                l_ne.setRootCause( e ) ;
+                throw l_ne ;
+            }
+        }
+        // Here we are moving the entry down into a deeper level and need to
+        // determine if we are to change the rdn or not.  If the first
+        // componenet of the oldName equals the first component of the newName
+        // then this is a simple move without an Rdn change.
+        else if( a_oldRdn.get( 0 ).equals( a_newRdn.get( 0 ) ) )
+        {
+            Name l_parentDn = l_newDn.getSuffix( 1 ) ;
+            LdapEntry l_parent = null ;
+
+            try
+            {
+                l_parent = l_nexus.read( l_parentDn ) ;
+            }
+            catch( BackendException e )
+            {
+                NamingException l_ne = new NamingException( "Failed rename "
+                    + "on old name '" + l_oldDn + "' to new name of '"
+                    + l_newDn + "' due to a nexus parent read error for a "
+                    + "parent with name '" + l_parentDn + "'." ) ;
+                l_ne.setRootCause(e) ;
+                throw l_ne ;
+            }
+
+            try
+            {
+                l_nexus.move( l_parent, l_oldEntry ) ;
+            }
+            catch( BackendException e )
+            {
+                NamingException l_ne = new NamingException( "Failed on nexus "
+                    + "move(" + l_parentDn + ", " + l_oldDn + ") due to a "
+                    + "backend failure." ) ;
+                l_ne.setRootCause( e ) ;
+                throw l_ne ;
+            }
+
+        // Here we are doing a move and a Rdn change at the same time.
+        }
+        else
+        {
+            Name l_parentDn = l_newDn.getSuffix( 1 ) ;
+            LdapEntry l_parent = null ;
+
+            try
+            {
+                l_parent = l_nexus.read( l_parentDn ) ;
+            }
+            catch( BackendException e )
+            {
+                NamingException l_ne = new NamingException( "Failed rename "
+                    + "on old name '" + l_oldDn + "' to new name of '"
+                    + l_newDn + "' due to a nexus parent read error for a "
+                    + "parent with name '" + l_parentDn + "'." ) ;
+                l_ne.setRootCause( e ) ;
+                throw l_ne ;
+            }
+
+            Name l_rdn = a_newRdn.getPrefix( 1 ) ;
+            try
+            {
+                l_nexus.move( l_parent, l_oldEntry, l_rdn, true ) ;
+            }
+            catch( BackendException e )
+            {
+                NamingException l_ne = new NamingException( "Failed on nexus "
+                    + "move(" + l_parentDn + ", " + l_oldDn + ", " + l_rdn
+                    + ", true) " + "due to a backend failure." ) ;
+                l_ne.setRootCause( e ) ;
+                throw l_ne ;
+            }
+        }
+    }
+
+
+    public void rename( String a_oldRdn, String a_newRdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        rename( l_nexus.getNormalizedName( a_oldRdn ),
+            l_nexus.getNormalizedName( a_newRdn ) ) ;
+    }
+
+
+    /**
+     * Destroys subcontexts by first building the distinguished name of the
+     * entry to destroy using the supplied relative distinguished name and
+     * the name of this node.
+     *
+     * @param a_rdn relative distinguished name describing a subordinate context
+     * to this one.
+     */
+    public void destroySubcontext( Name a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+		LdapEntry l_entry = m_ctx.getEntry() ;
+        LdapEntry l_oldEntry = null ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            l_oldEntry = l_nexus.read( l_dn ) ;
+
+            // The exception here is equivalent to an
+            if( l_nexus.isSuffix( l_oldEntry ) )
+            {
+				StringBuffer l_buf = new StringBuffer() ;
+				l_buf.append( "[53] Entry with Dn '" ) ;
+				l_buf.append( l_dn.toString() ) ;
+				l_buf.append( "' is a suffix.  Will not allow the deletion" ) ;
+				l_buf.append( " of a suffix entry!  To remove suffix" ) ;
+				l_buf.append( " detach the backend from the server by" ) ;
+				l_buf.append( " removing the backend from the server's" ) ;
+				l_buf.append( " config.xml file." ) ;
+				String l_msg = l_buf.toString() ;
+ 	   			throw new OperationNotSupportedException( l_msg ) ;
+            }
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "read(" + l_dn + ") due to a backend failure." ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+
+        try
+        {
+            l_nexus.delete( l_oldEntry ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "delete(" + l_dn + ") due to a backend failure." ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    public void destroySubcontext( String a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        destroySubcontext( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    public Context createSubcontext( Name a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        LdapEntry l_oldEntry = null ;
+
+        // The argument name is really the name relative to this context so we
+        // need to build out the fully qualified name a.k.a. distinguished name
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getUnNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            l_oldEntry = l_nexus.newEntry( l_dn.toString() ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "newEntry(" + l_dn + ") due to a backend failure." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+
+        String l_rdn = a_rdn.get( 0 ) ;
+        String l_rdnAttribute = NamespaceTools.getRdnAttribute( l_rdn ) ;
+        String l_rdnValue = NamespaceTools.getRdnValue( l_rdn ) ;
+        l_oldEntry.addValue( l_rdnAttribute, l_rdnValue ) ;
+        l_oldEntry.addValue( OBJECTCLASS_ATTR, JCONTAINER_ATTR ) ;
+        l_oldEntry.addValue( OBJECTCLASS_ATTR, TOP_ATTR ) ;
+
+        try
+        {
+            l_nexus.create( l_oldEntry ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "create(" + l_dn + ") due to a backend failure on entry:\n"
+                + l_oldEntry ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+
+        return new UnifiedLdapContext( m_ctx.getEnvironment(),
+            l_oldEntry ) ;
+    }
+
+
+    public Context createSubcontext( String a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return createSubcontext( l_nexus.getName( a_rdn ) ) ;
+    }
+
+
+    public NamingEnumeration list( Name a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Cursor l_children = null ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            l_children = l_nexus.listChildren( l_dn ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "listChildren(" + l_dn + ") due to a backend failure." ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+
+        return new NameClassPairEnumeration( l_nexus, l_children ) ;
+    }
+
+
+    public NamingEnumeration list(String a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return list( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    public NamingEnumeration listBindings( Name a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Cursor l_children = null ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            l_children = l_nexus.listChildren( l_dn ) ;
+        }
+        catch( BackendException e )
+        {
+            NamingException l_ne = new NamingException( "Failed on nexus "
+                + "listChildren("+l_dn+") due to a backend failure." ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+
+        return new BindingEnumeration( m_ctx.getEnvironment(), l_children ) ;
+    }
+
+
+    public NamingEnumeration listBindings( String a_rdn ) throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return listBindings( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    ////////////////////////////////////////////////
+    // Package Friendly & Private Utility Methods //
+    ////////////////////////////////////////////////
+
+
+    static Object deserialize( LdapEntry a_entry )
+        throws NamingException
+    {
+        ObjectInputStream l_in = null ;
+        String l_className = ( String )
+            a_entry.getSingleValue( JCLASSNAME_ATTR ) ;
+
+        try
+        {
+            byte [] l_data = ( byte [] )
+                a_entry.getSingleValue( JSERIALDATA_ATTR ) ;
+            l_in = new ObjectInputStream( new ByteArrayInputStream( l_data ) ) ;
+            Object l_obj = l_in.readObject() ;
+            return l_obj ;
+        }
+        catch( Exception e )
+        {
+            NamingException l_ne = new NamingException( "De-serialization of '"
+                + l_className + "' instance failed:\n" + e.getMessage() ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+        finally
+        {
+            try
+            {
+                l_in.close() ;
+            }
+            catch( IOException e )
+            {
+                throw new NamingException(
+                    "object deserialization stream close() failure" ) ;
+            }
+        }
+    }
+
+
+    static byte [] serialize( Object a_obj )
+        throws NamingException
+    {
+        ByteArrayOutputStream l_bytesOut = null ;
+        ObjectOutputStream l_out = null ;
+
+        try
+        {
+            l_bytesOut = new ByteArrayOutputStream() ;
+            l_out = new ObjectOutputStream( l_bytesOut ) ;
+            l_out.writeObject( a_obj ) ;
+            return l_bytesOut.toByteArray() ;
+        }
+        catch( Exception e )
+        {
+            NamingException l_ne = new NamingException( "Serialization of '"
+                + a_obj + "' failed:\n" + e.getMessage() ) ;
+            l_ne.setRootCause( e ) ;
+            throw l_ne ;
+        }
+        finally
+        {
+            try
+            {
+                l_out.close() ;
+            }
+            catch( IOException e )
+            {
+                throw new NamingException(
+                    "object serialization stream close() failure" ) ;
+            }
+        }
+    }
+
+
+    static void populate( LdapEntry a_entry, Name a_rdn, Object a_obj )
+        throws NamingException
+    {
+        // Add the rdn attribute
+        a_entry.addValue(NamespaceTools.getRdnAttribute( a_rdn.get( 0 ) ),
+            NamespaceTools.getRdnValue( a_rdn.get( 0 ) ) ) ;
+
+        // Let's add the object classes first:
+        //  objectClass: top
+        //  objectClass: javaObject
+        //  objectClass: javaContainer
+        //  objectClass: javaSerializedObject
+        a_entry.addValue( OBJECTCLASS_ATTR, TOP_ATTR ) ;
+        a_entry.addValue( OBJECTCLASS_ATTR, JOBJECT_ATTR ) ;
+        a_entry.addValue( OBJECTCLASS_ATTR, JCONTAINER_ATTR ) ;
+        a_entry.addValue( OBJECTCLASS_ATTR, JSERIALIZEDOBJ_ATTR ) ;
+
+        // Add the javaClassName and javaSerializedData attributes
+        a_entry.addValue( JCLASSNAME_ATTR, a_obj.getClass().getName() ) ;
+        a_entry.addValue( JSERIALDATA_ATTR, serialize( a_obj ) ) ;
+
+        // Add all the class names this object can be cast to:
+        Class [] l_classes = a_obj.getClass().getClasses() ;
+        for( int ii = 0; ii < l_classes.length; ii++ )
+        {
+            a_entry.addValue( JCLASSNAMES_ATTR, l_classes[ii].getName() ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/DirContextHelper.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/DirContextHelper.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,773 @@
+/*
+ * $Id: DirContextHelper.java,v 1.5 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import javax.naming.directory.DirContext;
+import org.apache.eve.backend.UnifiedBackend;
+import org.apache.eve.backend.LdapEntry;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.Name;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.eve.backend.BackendException;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.BasicAttribute;
+import java.util.Collection;
+import java.util.Iterator;
+import javax.naming.directory.NoSuchAttributeException;
+import javax.naming.directory.ModificationItem;
+import javax.naming.NamingEnumeration;
+import java.util.HashSet;
+import javax.naming.directory.SearchControls;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.BranchNode;
+import org.apache.ldap.common.filter.PresenceNode;
+import java.util.ArrayList;
+import org.apache.ldap.common.filter.SimpleNode;
+import org.apache.eve.backend.Cursor;
+import org.apache.ldap.common.filter.FilterParser;
+import org.apache.ldap.common.filter.FilterParserImpl;
+import java.io.IOException;
+import java.text.ParseException;
+
+
+public class DirContextHelper
+{
+    private final UnifiedDirContext m_ctx ;
+
+
+    DirContextHelper( UnifiedDirContext a_dirCtx )
+    {
+        m_ctx = a_dirCtx ;
+    }
+
+
+    public Attributes getAttributes( Name a_rdn )
+        throws NamingException
+    {
+        return getAttributes( getEntry( a_rdn ), null ) ;
+    }
+
+
+    public Attributes getAttributes( String a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return getAttributes( getEntry( l_nexus.getNormalizedName( a_rdn ) ), null ) ;
+    }
+
+
+    public Attributes getAttributes(Name name, String[] attrIds)
+	    throws NamingException
+    {
+        return getAttributes(getEntry(name), attrIds) ;
+    }
+
+
+    public Attributes getAttributes(String name, String[] attrIds)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return getAttributes(l_nexus.getNormalizedName(name), attrIds) ;
+    }
+
+
+    public void modifyAttributes(Name name, int mod_op, Attributes attrs)
+	    throws NamingException
+    {
+        LdapEntry l_entry = getEntry(name) ;
+        modify(l_entry, attrs, mod_op) ;
+        update(l_entry) ;
+    }
+
+
+    public void modifyAttributes(String name, int mod_op, Attributes attrs)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        modifyAttributes(l_nexus.getNormalizedName(name), mod_op, attrs) ;
+    }
+
+
+    public void modifyAttributes( Name name, ModificationItem[] mods )
+	    throws NamingException
+    {
+        LdapEntry l_entry = getEntry(name) ;
+
+        for(int ii = 0; ii < mods.length; ii++) {
+            ModificationItem l_mod = mods[ii] ;
+            switch(l_mod.getModificationOp()) {
+            case(DirContext.ADD_ATTRIBUTE):
+                add(l_entry, l_mod.getAttribute()) ;
+                break ;
+            case(DirContext.REMOVE_ATTRIBUTE):
+                remove(l_entry, l_mod.getAttribute()) ;
+                break ;
+            case(DirContext.REPLACE_ATTRIBUTE):
+                replace(l_entry, l_mod.getAttribute()) ;
+                break ;
+            default:
+                throw new NamingException("Unidentified modification "
+                + "operation: " + l_mod.getModificationOp()) ;
+            }
+        }
+
+        update(l_entry) ;
+    }
+
+
+    public void modifyAttributes(String name, ModificationItem[] mods)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        modifyAttributes(l_nexus.getNormalizedName(name), mods) ;
+    }
+
+
+    public void bind(Name name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        LdapEntry l_entry = null ;
+
+        if(null == obj && null == attrs) {
+            throw new NamingException("Both the obj and attrs args were null. "
+                + "At least one of these parameters must not be null.") ;
+        }
+
+        l_entry = newEntry(name) ;
+        if(obj != null) {
+            l_entry = getEntry(name) ;
+            ContextHelper.populate(l_entry, name, obj) ;
+        }
+
+        if(attrs != null) {
+            modify(l_entry, attrs, DirContext.ADD_ATTRIBUTE) ;
+        }
+
+        create(l_entry) ;
+    }
+
+
+    public void bind(String name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        bind(l_nexus.getNormalizedName(name), obj, attrs) ;
+    }
+
+
+    public void rebind(Name name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        if(hasEntry(name)) {
+            m_ctx.unbind(name) ;
+        }
+
+        bind(name, obj, attrs) ;
+    }
+
+
+    public void rebind(String name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        rebind(l_nexus.getNormalizedName(name), obj, attrs) ;
+    }
+
+
+    public DirContext createSubcontext( Name a_name, Attributes a_attrs )
+	    throws NamingException
+    {
+        LdapEntry l_entry = null ;
+
+        if( null == a_attrs )
+        {
+            m_ctx.createSubcontext( a_name ) ;
+        }
+
+        l_entry = newEntry( a_name ) ;
+        modify( l_entry, a_attrs, DirContext.ADD_ATTRIBUTE ) ;
+        create( l_entry ) ;
+        return new
+            UnifiedLdapContext( m_ctx.getEnvironment(), l_entry ) ;
+    }
+
+
+    public DirContext createSubcontext( String a_name, Attributes a_attrs )
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return createSubcontext( l_nexus.getName( a_name ), a_attrs) ;
+    }
+
+
+    ///////////////////////////////////
+    // Search Method Implementations //
+    ///////////////////////////////////
+
+
+    /**
+     * Single level scope search using this helper's context as the base DN.
+     * It uses the default search controls specified by the default
+     * SearchControls constructor.
+     */
+    public NamingEnumeration search(Name name,
+	                Attributes matchingAttributes,
+	                String[] attributesToReturn)
+	    throws NamingException
+    {
+        Cursor l_cursor = null ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+
+        // If matchingAttributes is null or empty then all children under this
+        // context are returned.
+        if(null == matchingAttributes || matchingAttributes.size() == 0) {
+            l_cursor = listChildren(name) ;
+        } else {
+            l_cursor = search(getExprNode(matchingAttributes), name,
+                SearchControls.ONELEVEL_SCOPE) ;
+        }
+
+        return new SearchResultEnumeration(m_ctx, l_nexus, l_cursor,
+            attributesToReturn, new SearchControls()) ;
+    }
+
+
+    public NamingEnumeration search(String name,
+	                Attributes matchingAttributes,
+	                String[] attributesToReturn)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return search(l_nexus.getName(name), matchingAttributes,
+            attributesToReturn) ;
+    }
+
+
+    public NamingEnumeration search(Name name,
+	                Attributes matchingAttributes)
+	    throws NamingException
+    {
+        return search(name, matchingAttributes, null) ;
+    }
+
+
+    public NamingEnumeration search(String name,
+	                Attributes matchingAttributes)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return search(l_nexus.getName(name), matchingAttributes, null) ;
+    }
+
+
+    public NamingEnumeration search(Name name,
+	                String filter,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        Cursor l_cursor = search(getExprNode(filter), name,
+            cons.getSearchScope()) ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return new SearchResultEnumeration(m_ctx, l_nexus, l_cursor,
+            null, cons) ;
+    }
+
+
+    public NamingEnumeration search(String name,
+	                String filter,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return search(l_nexus.getName(name), filter, cons) ;
+    }
+
+
+    public NamingEnumeration search(Name name,
+	                String filterExpr,
+	                Object[] filterArgs,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        Cursor l_cursor = search(getExprNode(filterExpr, filterArgs), name,
+            cons.getSearchScope()) ;
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return new SearchResultEnumeration(m_ctx, l_nexus, l_cursor,
+            null, cons) ;
+    }
+
+
+    public NamingEnumeration search(String name,
+	                String filterExpr,
+	                Object[] filterArgs,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        return search(l_nexus.getName(name), filterExpr, filterArgs, cons) ;
+    }
+
+
+    ////////////////////////////////////////////
+    // Private & Pkg Friendly Utility Methods //
+    ////////////////////////////////////////////
+
+
+    /**
+     * Adds attributes to an LdapEntry.
+     *
+     * @param a_entry the entry to add the attributes to
+     * @param a_attribute the set of attributes and their values to add.
+     */
+    static void add( LdapEntry a_entry, Attribute a_attribute )
+        throws NamingException
+    {
+        NamingEnumeration l_list = a_attribute.getAll() ;
+
+        while( l_list.hasMore() )
+        {
+            a_entry.addValue( a_attribute.getID(), l_list.next() ) ;
+        }
+    }
+
+
+    /**
+     * Removes values from the entry which are specified in the Attribute.  When
+     * the Attribute argument has no entries this method interprets the call to
+     * mean remove all values associated with the id of a_attribute for complete
+     * remove.  If there are some values associated with a_attribute then only
+     * those values are removed in a partial manner.
+     *
+     * @param a_entry the LdapEntry to remove the values or attribute from
+     * @param a_attribute the attribute and/or its values to remove.
+     */
+    static void remove( LdapEntry a_entry, Attribute a_attribute )
+        throws NamingException
+    {
+        NamingEnumeration l_list = a_attribute.getAll() ;
+
+        // If a_attributes does have value then we only remove those values and
+        // not all of the values associated with the id of the attribute so this
+        // is a partial remove scenario
+        if( l_list.hasMore() )
+        {
+            while( l_list.hasMore() )
+            {
+                a_entry.removeValue( a_attribute.getID(), l_list.next() ) ;
+            }
+        }
+        // Here all values associated with the attribute are removed.
+        else
+        {
+            a_entry.removeValues( a_attribute.getID() ) ;
+        }
+    }
+
+
+    static void replace( LdapEntry a_entry, Attribute a_attribute )
+        throws NamingException
+    {
+        // Clear all values here for the attribute to replace.
+        a_entry.removeValues( a_attribute.getID() ) ;
+
+        // Now add all the new values for this attribute.
+        NamingEnumeration l_list = a_attribute.getAll() ;
+        while( l_list.hasMore() )
+        {
+            a_entry.addValue( a_attribute.getID(), l_list.next() ) ;
+        }
+    }
+
+
+    /**
+     * Modifies an entry according to a modification type using the attributes
+     * specified within an Attributes parameter.
+     *
+     * @param a_entry the LdapEntry to modify
+     * @param a_attributes the set of attributes and values to use in the
+     * modification
+     * @param a_modOp the modification type/operation to perform
+     */
+    static void modify( LdapEntry a_entry, Attributes a_attributes,
+        int a_modOp )
+        throws NamingException
+    {
+        NamingEnumeration l_list = a_attributes.getAll() ;
+
+        while( l_list.hasMore() )
+        {
+            Attribute l_attr = ( Attribute ) l_list.next() ;
+
+            switch( a_modOp )
+            {
+            case( DirContext.ADD_ATTRIBUTE ):
+                add( a_entry, l_attr ) ;
+                break ;
+            case( DirContext.REMOVE_ATTRIBUTE ):
+                remove( a_entry, l_attr ) ;
+                break ;
+            case( DirContext.REPLACE_ATTRIBUTE ):
+                replace( a_entry, l_attr ) ;
+                break ;
+            default:
+                // We put this exception into the OTHER category since the code
+                // catches the problem and is not an OPERATIONSERROR.
+                throw new NamingException(
+                    "[80] Unidentified modification operation: " + a_modOp ) ;
+            }
+        }
+    }
+
+
+    void update( LdapEntry a_entry )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+
+        try
+        {
+            l_nexus.update( a_entry ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException(
+                "Failed on entry update for '" + a_entry.getEntryDN() + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    void create( LdapEntry a_entry )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+
+        try
+        {
+            l_nexus.create( a_entry ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException(
+                "Failed on entry create for '" + a_entry.getEntryDN() + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    void delete( LdapEntry a_entry )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+
+        try
+        {
+            l_nexus.delete( a_entry ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException(
+                "Failed on entry delete for '" + a_entry.getEntryDN() + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    /**
+     * Utility method to create a new invalid entry that is not yet created in
+     * the backend.
+     *
+     * @param a_name the non-normalized relative dn of the new entry to
+     */
+    LdapEntry newEntry( Name a_name )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getUnNormalizedDN() ) ;
+        l_dn.addAll( a_name ) ;
+
+        try
+        {
+            return l_nexus.newEntry( l_dn.toString() ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException( "Failed on newEntry( "
+                + l_dn + " ) due to backend failure." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    /**
+     * Gets an LdapEntry from the appropriate DIB off the nexus using a name
+     * relative to the entry associated with the DirContext of this helper.
+     */
+    LdapEntry getEntry( Name a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_nexus.getName( l_entry.getEntryDN() ) ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            return l_nexus.read( l_dn ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException( "Failed on entry read "
+                + "for '" + l_dn + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    /**
+     * Checks for a entry from the appropriate DIB off the nexus using a name
+     * relative to the entry associated with the DirContext of this helper.
+     */
+    boolean hasEntry( Name a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            return l_nexus.hasEntry( l_dn ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException( "Failed on hasEntry "
+                + "for '" + l_dn + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    Cursor listChildren( Name a_rdn )
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+        try
+        {
+            return l_nexus.listChildren( l_dn ) ;
+        }
+        catch( BackendException be )
+        {
+            NamingException l_ne = new NamingException(
+                "Failed on listChildren for '" + l_dn + "'." ) ;
+            l_ne.setRootCause( be ) ;
+            throw l_ne ;
+        }
+    }
+
+
+    Cursor search(ExprNode a_filter, Name a_rn, int a_scope)
+        throws NamingException
+    {
+        UnifiedBackend l_nexus = JndiProviderModule.getInstance().getNexus() ;
+        LdapEntry l_entry = m_ctx.getEntry() ;
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( l_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rn ) ;
+
+        try {
+            return l_nexus.search(a_filter, l_dn, a_scope) ;
+        } catch(BackendException e) {
+            NamingException l_ne = new NamingException("Failed on search "
+                + "for '" + l_dn + "'.") ;
+            l_ne.setRootCause(e) ;
+            throw l_ne ;
+        }
+    }
+
+
+    /**
+     * @return attribute in a_entry for an attribute identitifier if the
+     * attribute exists.
+     * @throws NoSuchAttributeException if a_entry does not contain the
+     * requested attribute.
+     */
+    static Attribute getAttribute(LdapEntry a_entry, String a_attribName)
+        throws NoSuchAttributeException
+    {
+        BasicAttribute l_attrib = new BasicAttribute(a_attribName) ;
+        Collection l_values = (Collection) a_entry.getMultiValue(a_attribName) ;
+
+        // SCREAM if attribute does not exist.
+        if(null == l_values) {
+            throw new NoSuchAttributeException("Attribute " + a_attribName
+                + " does not exist within entry '"
+                + a_entry.getEntryDN() + "'") ;
+        }
+
+        Iterator l_list = l_values.iterator() ;
+        while(l_list.hasNext()) {
+            l_attrib.add(l_list.next()) ;
+        }
+
+        return l_attrib ;
+    }
+
+
+    /**
+     * Generates the set of attributes for an entry using a specified attribute
+     * list to select for specific attributes.  If the attribute list array is
+     * null all attributes are packaged and returned.
+     */
+    static Attributes getAttributes(LdapEntry a_entry, String [] attribList)
+        throws NamingException
+    {
+        // Don't need this bullshit of the entry does it for us already.
+        HashSet l_lut = null ;
+
+        // Optionally create fast normalized lookup table for attribute ids
+        if(attribList != null) {
+            // Hash lowercased versions of attributes so we do not generate strs
+            // over and over again while searching through attribute list.
+            l_lut = new HashSet(attribList.length) ;
+            for(int ii = 0; ii < attribList.length; ii++) {
+                String l_lower = attribList[ii].toLowerCase() ;
+                l_lut.add(l_lower) ;
+            }
+        }
+
+        // Iterate through list of attributes and add them to the new Attributes
+        // instance based on the attribute list array if it was not null
+        // otherwise we return all attributes.
+        BasicAttributes l_attributes = new BasicAttributes(true) ;
+        Iterator l_list = a_entry.attributes().iterator() ;
+        while(l_list.hasNext()) {
+            String l_attribName = (String) l_list.next() ;
+
+            // If l_lut exists we add the attribute only if it is in the lut
+            if(l_lut != null && l_lut.contains(l_attribName.toLowerCase())) {
+                l_attributes.put(getAttribute(a_entry, l_attribName)) ;
+            // Lut is null so we add all attributes.
+            } else if(null == l_lut) {
+                l_attributes.put(getAttribute(a_entry, l_attribName)) ;
+            }
+
+            // If lut is not null but the attribute name is not present in
+            // it as a key then we do not include the attribute in the response.
+        }
+
+        return l_attributes ;
+    }
+
+
+    /**
+     * Builds an expression tree that matches for a set of attribute value
+     * pairs under one AND expression.  If an attribute does not have any
+     * values then it is a presence assertion node.  Otherwise the attributes
+     * values are used in as many equality expressions as there are values using
+     * that attributes identifier.
+     */
+    ExprNode getExprNode(Attributes l_attributes)
+        throws NamingException
+    {
+        ArrayList l_nodes = new ArrayList() ;
+        NamingEnumeration l_attrList = l_attributes.getAll() ;
+        while(l_attrList.hasMore()) {
+            Attribute l_attr = (Attribute) l_attrList.next() ;
+
+            if(l_attr.size() == 0) {
+                l_nodes.add(new PresenceNode(l_attr.getID())) ;
+            } else {
+                NamingEnumeration l_values = l_attr.getAll() ;
+                while(l_values.hasMore()) {
+                    String l_val = (String) l_values.next() ;
+                    l_nodes.add(new SimpleNode(l_attr.getID(), l_val,
+                        SimpleNode.EQUALITY)) ;
+                }
+            }
+        }
+
+        return new BranchNode(BranchNode.AND, l_nodes) ;
+    }
+
+
+    static FilterParser s_parser = null ;
+    ExprNode getExprNode(String a_filter)
+        throws NamingException
+    {
+        if(null == s_parser) {
+            try {
+                s_parser = new FilterParserImpl() ;
+            } catch(IOException e) {
+                NamingException l_ne = new NamingException("Failed on "
+                    + "FilterParser init.") ;
+                l_ne.setRootCause(e) ;
+                throw l_ne ;
+            }
+        }
+
+        try {
+            return s_parser.parse(a_filter) ;
+        } catch(ParseException e) {
+            NamingException l_ne = new NamingException("Failed on "
+                + "FilterParser parse of filter:\n'" + a_filter + "'") ;
+            l_ne.setRootCause(e) ;
+            throw l_ne ;
+        } catch(IOException e) {
+            NamingException l_ne = new NamingException("Failed on "
+                + "FilterParser parse of filter:\n'" + a_filter + "'") ;
+            l_ne.setRootCause(e) ;
+            throw l_ne ;
+        }
+    }
+
+
+    ExprNode getExprNode(String a_filter, Object [] a_filterArgs)
+        throws NamingException
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+        StringBuffer l_tmp = new StringBuffer() ;
+        for(int ii = 0 ; ii < a_filter.length() ; ii++) {
+            if(a_filter.charAt(ii) == '{') {
+                ii++ ;
+                while(a_filter.charAt(ii) != '}') {
+                    l_tmp.append(a_filter.charAt(ii)) ;
+                    ii++ ;
+                }
+
+                int l_arg = Integer.parseInt(l_tmp.toString()) ;
+                l_buf.append(a_filterArgs[l_arg].toString()) ;
+            } else {
+                l_buf.append(a_filter.charAt(ii)) ;
+            }
+        }
+
+        return getExprNode(l_buf.toString()) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProvider.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProvider.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,25 @@
+/*
+ * $Id: JndiProvider.java,v 1.3 2003/03/13 18:27:32 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.NamingException ;
+import javax.naming.ldap.LdapContext ;
+
+
+public interface JndiProvider
+{
+    public static final String ROLE = JndiProvider.class.getName() ;
+
+    LdapContext getContext(Hashtable an_environment)
+        throws NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProviderModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/JndiProviderModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,190 @@
+/*
+ * $Id: JndiProviderModule.java,v 1.7 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.Context ;
+import javax.naming.NamingException ;
+import javax.naming.ldap.LdapContext ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.backend.UnifiedBackend ;
+
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.eve.client.ClientManager;
+
+
+/**
+ * Protocol engine stage: the request processing stage of the pipeline.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.jndi.JndiProvider"
+ * @phoenix:mx-topic name="JndiProviderModule"
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.7 $
+ */
+public class JndiProviderModule
+    extends AbstractModule
+    implements JndiProvider
+{
+    private static JndiProviderModule s_singleton = null ;
+    private UnifiedBackend m_nexus = null ;
+    private ClientManager m_clientManager = null ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a singlton instance of the JndiProvider for the entire JVM.
+     * Multiple calls to this method will raise an exception.
+     *
+     * @throws IllegalStateException if another JndiProvider has already been
+     * initialized.
+     */
+    public JndiProviderModule()
+    {
+        if( s_singleton != null )
+        {
+            throw new IllegalStateException(
+                "Cannot instantiate more than one Server-Side JndiProvider!" ) ;
+        }
+
+        s_singleton = this ;
+    }
+
+
+    static JndiProviderModule getInstance()
+    {
+        if( null == s_singleton )
+        {
+            throw new IllegalStateException(
+                "Cannot return singleton instance without initialization!" ) ;
+        }
+
+        return s_singleton ;
+    }
+
+
+	/**
+     * Creates a default context at the root DSE.
+     */
+    public LdapContext getContext( Hashtable an_environment )
+        throws NamingException
+    {
+        return new UnifiedLdapContext( an_environment ) ;
+    }
+
+
+
+    // ------------------------------------------------------------------------
+    // Avalon Lifecycle Methods & Other Module Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets a descriptive String for this JndiProvider implementation.
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "Server-Side JNDI Provider Module" ;
+    }
+
+
+    /**
+     * Gets the ROLE or fully qualified class name of the service interface
+     * associated with this implementation.
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation role.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets the fully qualified class name implementation class.
+     *
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation class name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    public void configure( Configuration a_config )
+    {
+        // Does nothing for now.
+    }
+
+
+    /**
+     * Gets a handle on the UnifiedBackend service aka NexusModule.
+     *
+     * @phoenix:dependency name="org.apache.eve.backend.UnifiedBackend"
+     */
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        m_nexus = ( UnifiedBackend ) a_manager.lookup( UnifiedBackend.ROLE ) ;
+    }
+
+
+    public void stop()
+    {
+        s_singleton = null ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Package friendly methods used by contexts and their helpers
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the ClientManager this ClientManagerSlave subordinates to.
+     *
+     * @return the ClientManager master
+     */
+    ClientManager getClientManager()
+    {
+        return m_clientManager ;
+    }
+
+
+    /**
+     * Gets a handle on the UnifiedBackend this module and its Contexts and
+     * helpers need to perform operations against backends.
+     *
+     * @return a handle on the backend nexus
+     */
+    UnifiedBackend getNexus()
+    {
+        return m_nexus ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/NameClassPairEnumeration.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/NameClassPairEnumeration.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,99 @@
+/*
+ * $Id: NameClassPairEnumeration.java,v 1.3 2003/03/13 18:27:33 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+import javax.naming.NamingEnumeration;
+import org.apache.eve.backend.Cursor;
+import javax.naming.NamingException;
+import org.apache.eve.backend.LdapEntry;
+import javax.naming.NameClassPair;
+import org.apache.eve.backend.UnifiedBackend;
+import java.util.Hashtable;
+import org.apache.avalon.framework.ExceptionUtil;
+
+
+public class NameClassPairEnumeration
+    implements NamingEnumeration
+{
+    private final Cursor m_cursor ;
+    private final UnifiedBackend m_nexus ;
+
+
+    NameClassPairEnumeration(UnifiedBackend a_nexus, Cursor a_cursor)
+    {
+        m_nexus = a_nexus ;
+        m_cursor = a_cursor ;
+    }
+
+
+    public void close()
+        throws NamingException
+    {
+        m_cursor.close() ;
+    }
+
+
+    public boolean hasMore()
+        throws NamingException
+    {
+        return m_cursor.hasMore() ;
+    }
+
+
+    public Object next()
+        throws NamingException
+    {
+        String l_rdn = null ;
+        String l_class = null ;
+
+        LdapEntry l_entry = (LdapEntry) m_cursor.next() ;
+        if(l_entry.hasAttribute(ContextHelper.JCLASSNAME_ATTR)) {
+            l_class = (String)
+                l_entry.getSingleValue(ContextHelper.JCLASSNAME_ATTR) ;
+        } else {
+            l_class = UnifiedLdapContext.class.getName() ;
+        }
+
+        l_rdn = m_nexus.getNormalizedName(l_entry.getEntryDN()).get(0) ;
+        return new NameClassPair(l_rdn, l_class) ;
+    }
+
+
+    public boolean hasMoreElements()
+    {
+        return m_cursor.hasMoreElements() ;
+    }
+
+
+    public Object nextElement()
+    {
+        String l_rdn = null ;
+        String l_class = null ;
+
+        LdapEntry l_entry = (LdapEntry) m_cursor.nextElement() ;
+        if(l_entry.hasAttribute(ContextHelper.JCLASSNAME_ATTR)) {
+            l_class = (String)
+                l_entry.getSingleValue(ContextHelper.JCLASSNAME_ATTR) ;
+        } else {
+            l_class = UnifiedLdapContext.class.getName() ;
+        }
+
+        try {
+            l_rdn = m_nexus.getNormalizedName(l_entry.getEntryDN()).get(0) ;
+        } catch(NamingException e) {
+            try {
+                m_cursor.close() ;
+            } catch(Exception e2) { }
+            throw new java.util.NoSuchElementException("Premature close of "
+                + "backend cursor:\n" + ExceptionUtil.printStackTrace(e)) ;
+        }
+
+        return new NameClassPair(l_rdn, l_class) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/SearchResultEnumeration.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/SearchResultEnumeration.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,138 @@
+/*
+ * $Id: SearchResultEnumeration.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.HashMap ;
+
+import javax.naming.NamingEnumeration ;
+
+import org.apache.eve.backend.Cursor ;
+import javax.naming.directory.SearchResult ;
+import org.apache.eve.backend.LdapEntry ;
+import java.util.Iterator;
+import javax.naming.directory.BasicAttributes ;
+import javax.naming.directory.DirContext ;
+import javax.naming.Name ;
+import org.apache.eve.backend.UnifiedBackend ;
+import java.util.Collections ;
+import javax.naming.NamingException ;
+import org.apache.avalon.framework.ExceptionUtil ;
+import javax.naming.directory.SearchControls ;
+
+
+
+public class SearchResultEnumeration
+    implements NamingEnumeration
+{
+    private final String [] m_attribsToReturn ;
+    private final UnifiedBackend m_nexus ;
+    private final DirContext m_context ;
+    private final Cursor m_cursor ;
+    private final SearchControls m_ctls ;
+
+
+    SearchResultEnumeration(DirContext a_context,
+        UnifiedBackend a_nexus, Cursor a_cursor, SearchControls a_ctls)
+    {
+        this(a_context, a_nexus, a_cursor, null, a_ctls) ;
+    }
+
+
+    SearchResultEnumeration(DirContext a_context, UnifiedBackend a_nexus,
+        Cursor a_cursor, String [] a_attribsToReturn, SearchControls a_ctls)
+    {
+        m_ctls = a_ctls ;
+        m_nexus = a_nexus ;
+        m_cursor = a_cursor ;
+        m_context = a_context ;
+
+        if(a_attribsToReturn != null && a_attribsToReturn.length > 0) {
+            m_attribsToReturn = a_attribsToReturn ;
+        } else {
+            m_attribsToReturn = m_ctls.getReturningAttributes() ;
+        }
+    }
+
+
+    SearchResult getResult(LdapEntry a_entry)
+        throws NamingException
+    {
+        Object l_obj = null ;
+        BasicAttributes l_attribs = new BasicAttributes(true) ;
+
+        if(null == m_attribsToReturn) {
+            Iterator l_list = a_entry.attributes().iterator() ;
+            while(l_list.hasNext()) {
+                l_attribs.put(DirContextHelper.getAttribute(a_entry,
+                    (String) l_list.next())) ;
+            }
+        } else {
+            for(int ii = 0; ii < m_attribsToReturn.length; ii++) {
+                l_attribs.put(DirContextHelper.getAttribute(a_entry,
+                    m_attribsToReturn[ii])) ;
+            }
+        }
+
+        if(a_entry.hasAttribute(ContextHelper.JCLASSNAME_ATTR)) {
+            l_obj = ContextHelper.deserialize(a_entry) ;
+        } else {
+            l_obj = new UnifiedLdapContext( m_context.getEnvironment(),
+                a_entry ) ;
+        }
+
+        return new SearchResult(a_entry.getEntryDN(), l_obj, l_attribs, false) ;
+    }
+
+
+    public boolean hasMore()
+        throws NamingException
+    {
+        return m_cursor.hasMore() ;
+    }
+
+
+    public boolean hasMoreElements()
+    {
+        try {
+            return hasMore() ;
+        } catch(NamingException e) {
+            throw new java.util.NoSuchElementException("Could not get next "
+                + " element due to underlying exception:\n"
+                + ExceptionUtil.printStackTrace(e)) ;
+        }
+    }
+
+
+    public Object next()
+        throws NamingException
+    {
+        return getResult((LdapEntry) m_cursor.next()) ;
+    }
+
+
+    public Object nextElement()
+    {
+        try {
+            return next() ;
+        } catch(NamingException e) {
+            throw new java.util.NoSuchElementException("Could not get next "
+                + " element due to underlying exception:\n"
+                + ExceptionUtil.printStackTrace(e)) ;
+        }
+    }
+
+
+    public void close()
+        throws NamingException
+    {
+        m_cursor.close() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ServerContextFactory.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/ServerContextFactory.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,28 @@
+/*
+ * $Id: ServerContextFactory.java,v 1.3 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.Context ;
+import javax.naming.NamingException ;
+
+
+public class ServerContextFactory
+    implements javax.naming.spi.InitialContextFactory
+{
+    public Context getInitialContext( Hashtable an_envoronment )
+        throws NamingException
+    {
+        JndiProviderModule l_module = JndiProviderModule.getInstance() ;
+        return l_module.getContext( an_envoronment ) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedContext.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedContext.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,840 @@
+/*
+ * $Id: UnifiedContext.java,v 1.7 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.Name ;
+import javax.naming.Context ;
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+import javax.naming.ldap.LdapContext ;
+import javax.naming.NamingEnumeration ;
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.client.ClientManager ;
+import org.apache.eve.backend.UnifiedBackend ;
+
+
+/**
+ * Base Context method implementations are placed here.  The ContextHelper is
+ * used to contain methods larger than a few lines.  In general because the
+ * Context interface is so huge, we try to relocate functionality to the
+ * context helper where we can.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.7 $
+ */
+public abstract class UnifiedContext
+    implements Context
+{
+    /** The relative distinguished name represented by this context */
+    protected final Name m_rdn ;
+    /** The environment for this context */
+    protected final Hashtable m_env ;
+    /** The entry this context represents */
+    protected final LdapEntry m_entry ;
+	/** The helper used by this context */
+    protected final ContextHelper m_helper ;
+
+
+    /**
+     * Creates the default context pointing to the RootDSE using the empty DN.
+     *
+     * @param an_environment the environment setting for the context
+     */
+    protected UnifiedContext( Hashtable an_environment )
+    {
+        m_env = ( Hashtable ) an_environment.clone() ;
+        m_rdn = new LdapName() ;
+
+        JndiProviderModule l_provider = JndiProviderModule.getInstance() ;
+        UnifiedBackend l_nexus = l_provider.getNexus() ;
+        m_entry = l_nexus.getRootDSE() ;
+        m_helper = new ContextHelper( this ) ;
+    }
+
+
+    /**
+     * Creates a context around an LdapEntry at a specific point in the DIT.
+     *
+     * @param an_environment the environment setting for the context
+     * @param a_entry the entry this context represents
+     */
+    protected UnifiedContext( Hashtable an_environment, LdapEntry a_entry )
+        throws NamingException
+    {
+        m_env = ( Hashtable ) an_environment.clone() ;
+
+		// Set rdn to the first Name component of unnormalized Dn of the entry
+        m_rdn = new LdapName() ;
+        Name l_dn = a_entry.getUnNormalizedDN() ;
+        m_rdn.add( l_dn.get( 0 ) ) ;
+
+        m_entry = a_entry ;
+        m_helper = new ContextHelper( this ) ;
+    }
+
+
+    /////////////////////////////
+    // Context Implementations //
+    /////////////////////////////
+
+
+    /**
+     * Retrieves the named object.
+     * If <tt>name</tt> is empty, returns a new instance of this context
+     * (which represents the same naming context as this context, but its
+     * environment may be modified independently and it may be accessed
+     * concurrently).
+     *
+     * @param a_rdn
+     *		the name of the object to look up relative to this context
+     * @return	the object bound to <tt>name</tt>
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #lookup(String)
+     * @see #lookupLink(Name)
+     */
+    public Object lookup( Name a_rdn ) throws NamingException
+    {
+        return m_helper.lookup( a_rdn ) ;
+    }
+
+
+    /**
+     * Retrieves the named object.
+     * See {@link #lookup(Name)} for details.
+     * @param a_rdn
+     *		the name of the object to look up relative to this context.
+     * @return	the object bound to <tt>name</tt>
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Object lookup( String a_rdn ) throws NamingException
+    {
+        return m_helper.lookup( a_rdn ) ;
+    }
+
+
+    /**
+     * Binds a name to an object.
+     * All intermediate contexts and the target context (that named by all
+     * but terminal atomic component of the name) must already exist.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @throws	NamingException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *	 	if object did not supply all mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #bind(String, Object)
+     * @see #rebind(Name, Object)
+     * @see javax.naming.directory.DirContext#bind(Name, Object,
+     *		javax.naming.directory.Attributes)
+     */
+    public void bind(Name name, Object obj) throws NamingException
+    {
+        m_helper.bind(name, obj) ;
+    }
+
+
+    /**
+     * Binds a name to an object.
+     * See {@link #bind(Name, Object)} for details.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @throws	javax.naming.NameAlreadyBoundException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *	 	if object did not supply all mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void bind(String name, Object obj) throws NamingException
+    {
+        m_helper.bind(name, obj) ;
+    }
+
+
+    /**
+     * Binds a name to an object, overwriting any existing binding.
+     * All intermediate contexts and the target context (that named by all
+     * but terminal atomic component of the name) must already exist.
+     *
+     * <p> If the object is a <tt>DirContext</tt>, any existing attributes
+     * associated with the name are replaced with those of the object.
+     * Otherwise, any existing attributes associated with the name remain
+     * unchanged.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *	 	if object did not supply all mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #rebind(String, Object)
+     * @see #bind(Name, Object)
+     * @see javax.naming.directory.DirContext#rebind(Name, Object,
+     *		javax.naming.directory.Attributes)
+     * @see <{DirContext}>
+     */
+    public void rebind(Name name, Object obj) throws NamingException
+    {
+        m_helper.rebind(name, obj) ;
+    }
+
+
+    /**
+     * Binds a name to an object, overwriting any existing binding.
+     * See {@link #rebind(Name, Object)} for details.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *	 	if object did not supply all mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void rebind(String name, Object obj) throws NamingException
+    {
+        m_helper.rebind(name, obj) ;
+    }
+
+
+    /**
+     * Unbinds the named object.
+     * Removes the terminal atomic name in <code>name</code>
+     * from the target context--that named by all but the terminal
+     * atomic part of <code>name</code>.
+     *
+     * <p> This method is idempotent.
+     * It succeeds even if the terminal atomic name
+     * is not bound in the target context, but throws
+     * <tt>NameNotFoundException</tt>
+     * if any of the intermediate contexts do not exist.
+     *
+     * <p> Any attributes associated with the name are removed.
+     * Intermediate contexts are not changed.
+     *
+     * @param name
+     *		the name to unbind; may not be empty
+     * @throws	javax.naming.NameNotFoundException if an intermediate context does not exist
+     * @throws	NamingException if a naming exception is encountered
+     * @see #unbind(String)
+     */
+    public void unbind(Name name) throws NamingException
+    {
+        m_helper.unbind(name) ;
+    }
+
+
+    /**
+     * Unbinds the named object.
+     * See {@link #unbind(Name)} for details.
+     *
+     * @param name
+     *		the name to unbind; may not be empty
+     * @throws	javax.naming.NameNotFoundException if an intermediate context does not exist
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void unbind(String name) throws NamingException
+    {
+        m_helper.unbind(name) ;
+    }
+
+
+    /**
+     * Binds a new name to the object bound to an old name, and unbinds
+     * the old name.  Both names are relative to this context.
+     * Any attributes associated with the old name become associated
+     * with the new name.
+     * Intermediate contexts of the old name are not changed.
+     *
+     * @param oldName
+     *		the name of the existing binding; may not be empty
+     * @param newName
+     *		the name of the new binding; may not be empty
+     * @throws	javax.naming.NameAlreadyBoundException if <tt>newName</tt> is already bound
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #rename(String, String)
+     * @see #bind(Name, Object)
+     * @see #rebind(Name, Object)
+     */
+    public void rename(Name oldName, Name newName) throws NamingException
+    {
+        m_helper.rename(oldName, newName) ;
+    }
+
+
+    /**
+     * Binds a new name to the object bound to an old name, and unbinds
+     * the old name.
+     * See {@link #rename(Name, Name)} for details.
+     *
+     * @param oldName
+     *		the name of the existing binding; may not be empty
+     * @param newName
+     *		the name of the new binding; may not be empty
+     * @throws	javax.naming.NameAlreadyBoundException if <tt>newName</tt> is already bound
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void rename(String oldName, String newName) throws NamingException
+    {
+        m_helper.rename(oldName, newName) ;
+    }
+
+
+    /**
+     * Enumerates the names bound in the named context, along with the
+     * class names of objects bound to them.
+     * The contents of any subcontexts are not included.
+     *
+     * <p> If a binding is added to or removed from this context,
+     * its effect on an enumeration previously returned is undefined.
+     *
+     * @param name
+     *		the name of the context to list
+     * @return	an enumeration of the names and class names of the
+     *		bindings in this context.  Each element of the
+     *		enumeration is of type <tt>NameClassPair</tt>.
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #list(String)
+     * @see #listBindings(Name)
+     * @see javax.naming.NameClassPair
+     */
+    public NamingEnumeration list(Name name) throws NamingException
+    {
+        return m_helper.list(name) ;
+    }
+
+
+    /**
+     * Enumerates the names bound in the named context, along with the
+     * class names of objects bound to them.
+     * See {@link #list(Name)} for details.
+     *
+     * @param name
+     *		the name of the context to list
+     * @return	an enumeration of the names and class names of the
+     *		bindings in this context.  Each element of the
+     *		enumeration is of type <tt>NameClassPair</tt>.
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration list(String name) throws NamingException
+    {
+        return m_helper.list(name) ;
+    }
+
+
+    /**
+     * Enumerates the names bound in the named context, along with the
+     * objects bound to them.
+     * The contents of any subcontexts are not included.
+     *
+     * <p> If a binding is added to or removed from this context,
+     * its effect on an enumeration previously returned is undefined.
+     *
+     * @param name
+     *		the name of the context to list
+     * @return	an enumeration of the bindings in this context.
+     *		Each element of the enumeration is of type
+     *		<tt>Binding</tt>.
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #listBindings(String)
+     * @see #list(Name)
+     * @see javax.naming.Binding
+      */
+    public NamingEnumeration listBindings(Name name) throws NamingException
+    {
+        return m_helper.listBindings(name) ;
+    }
+
+
+    /**
+     * Enumerates the names bound in the named context, along with the
+     * objects bound to them.
+     * See {@link #listBindings(Name)} for details.
+     *
+     * @param name
+     *		the name of the context to list
+     * @return	an enumeration of the bindings in this context.
+     *		Each element of the enumeration is of type
+     *		<tt>Binding</tt>.
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration listBindings(String name) throws NamingException
+    {
+        return m_helper.listBindings(name) ;
+    }
+
+
+    /**
+     * Destroys the named context and removes it from the namespace.
+     * Any attributes associated with the name are also removed.
+     * Intermediate contexts are not destroyed.
+     *
+     * <p> This method is idempotent.
+     * It succeeds even if the terminal atomic name
+     * is not bound in the target context, but throws
+     * <tt>NameNotFoundException</tt>
+     * if any of the intermediate contexts do not exist.
+     *
+     * <p> In a federated naming system, a context from one naming system
+     * may be bound to a name in another.  One can subsequently
+     * look up and perform operations on the foreign context using a
+     * composite name.  However, an attempt destroy the context using
+     * this composite name will fail with
+     * <tt>NotContextException</tt>, because the foreign context is not
+     * a "subcontext" of the context in which it is bound.
+     * Instead, use <tt>unbind()</tt> to remove the
+     * binding of the foreign context.  Destroying the foreign context
+     * requires that the <tt>destroySubcontext()</tt> be performed
+     * on a context from the foreign context's "native" naming system.
+     *
+     * @param name
+     *		the name of the context to be destroyed; may not be empty
+     * @throws	javax.naming.NameNotFoundException if an intermediate context does not exist
+     * @throws	javax.naming.NotContextException if the name is bound but does not name a
+     *		context, or does not name a context of the appropriate type
+     * @throws	javax.naming.ContextNotEmptyException if the named context is not empty
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #destroySubcontext(String)
+     */
+    public void destroySubcontext( Name name ) throws NamingException
+    {
+        m_helper.destroySubcontext( name ) ;
+    }
+
+
+    /**
+     * Destroys the named context and removes it from the namespace.
+     * See {@link #destroySubcontext(Name)} for details.
+     *
+     * @param name
+     *		the name of the context to be destroyed; may not be empty
+     * @throws	javax.naming.NameNotFoundException if an intermediate context does not exist
+     * @throws	javax.naming.NotContextException if the name is bound but does not name a
+     *		context, or does not name a context of the appropriate type
+     * @throws	javax.naming.ContextNotEmptyException if the named context is not empty
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void destroySubcontext( String name ) throws NamingException
+    {
+        m_helper.destroySubcontext( name ) ;
+    }
+
+
+    /**
+     * Creates and binds a new context.
+     * Creates a new context with the given name and binds it in
+     * the target context (that named by all but terminal atomic
+     * component of the name).  All intermediate contexts and the
+     * target context must already exist.
+     *
+     * @param a_name
+     *		the name of the context to create; may not be empty
+     * @return	the newly created context
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *		if creation of the subcontext requires specification of
+     *		mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #createSubcontext(String)
+     * @see javax.naming.directory.DirContext#createSubcontext
+     */
+    public Context createSubcontext( Name a_name )
+        throws NamingException
+    {
+        return m_helper.createSubcontext( a_name ) ;
+    }
+
+
+    /**
+     * Creates and binds a new context.
+     * See {@link #createSubcontext(Name)} for details.
+     *
+     * @param a_name
+     *		the name of the context to create; may not be empty
+     * @return	the newly created context
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException
+     *		if creation of the subcontext requires specification of
+     *		mandatory attributes
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Context createSubcontext( String a_name )
+        throws NamingException
+    {
+        return m_helper.createSubcontext( a_name ) ;
+    }
+
+
+    /**
+     * Retrieves the named object, following links except
+     * for the terminal atomic component of the name.
+     * If the object bound to <tt>name</tt> is not a link,
+     * returns the object itself.
+     *
+     * @param name
+     *		the name of the object to look up
+     * @return	the object bound to <tt>name</tt>, not following the
+     *		terminal link (if any).
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #lookupLink(String)
+     */
+    public Object lookupLink(Name name) throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the named object, following links except
+     * for the terminal atomic component of the name.
+     * See {@link #lookupLink(Name)} for details.
+     *
+     * @param name
+     *		the name of the object to look up
+     * @return	the object bound to <tt>name</tt>, not following the
+     *		terminal link (if any)
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Object lookupLink(String name) throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the parser associated with the named context.
+     * In a federation of namespaces, different naming systems will
+     * parse names differently.  This method allows an application
+     * to get a parser for parsing names into their atomic components
+     * using the naming convention of a particular naming system.
+     * Within any single naming system, <tt>NameParser</tt> objects
+     * returned by this method must be equal (using the <tt>equals()</tt>
+     * test).
+     *
+     * @param a_rdn
+     *		the name of the context from which to get the parser
+     * @return	a name parser that can parse compound names into their atomic
+     *		components
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #getNameParser(String)
+     * @see javax.naming.CompoundName
+     */
+    public NameParser getNameParser( Name a_rdn ) throws NamingException
+    {
+        Name l_dn = new LdapName() ;
+        l_dn.addAll( m_entry.getNormalizedDN() ) ;
+        l_dn.addAll( a_rdn ) ;
+
+		JndiProviderModule l_provider = JndiProviderModule.getInstance() ;
+        UnifiedBackend l_nexus = l_provider.getNexus() ;
+        return l_nexus.getNormalizingParser( l_dn ) ;
+    }
+
+
+    /**
+     * Retrieves the parser associated with the named context.
+     * See {@link #getNameParser(Name)} for details.
+     *
+     * @param a_rdn
+     *		the name of the context from which to get the parser
+     * @return	a name parser that can parse compound names into their atomic
+     *		components
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NameParser getNameParser( String a_rdn ) throws NamingException
+    {
+		JndiProviderModule l_provider = JndiProviderModule.getInstance() ;
+        UnifiedBackend l_nexus = l_provider.getNexus() ;
+        return getNameParser( l_nexus.getNormalizedName( a_rdn ) ) ;
+    }
+
+
+    /**
+     * Composes the name of this context with a name relative to
+     * this context.
+     * Given a name (<code>name</code>) relative to this context, and
+     * the name (<code>prefix</code>) of this context relative to one
+     * of its ancestors, this method returns the composition of the
+     * two names using the syntax appropriate for the naming
+     * system(s) involved.  That is, if <code>name</code> names an
+     * object relative to this context, the result is the name of the
+     * same object, but relative to the ancestor context.  None of the
+     * names may be null.
+     * <p>
+     * For example, if this context is named "wiz.com" relative
+     * to the initial context, then
+     * <pre>
+     *	composeName("east", "wiz.com")	</pre>
+     * might return <code>"east.wiz.com"</code>.
+     * If instead this context is named "org/research", then
+     * <pre>
+     *	composeName("user/jane", "org/research")	</pre>
+     * might return <code>"org/research/user/jane"</code> while
+     * <pre>
+     *	composeName("user/jane", "research")	</pre>
+     * returns <code>"research/user/jane"</code>.
+     *
+     * @param name
+     *		a name relative to this context
+     * @param prefix
+     *		the name of this context relative to one of its ancestors
+     * @return	the composition of <code>prefix</code> and <code>name</code>
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #composeName(String, String)
+     */
+    public Name composeName(Name name, Name prefix)
+        throws NamingException
+    {
+        return m_helper.composeName(name, prefix) ;
+    }
+
+
+    /**
+     * Composes the name of this context with a name relative to
+     * this context.
+     * See {@link #composeName(Name, Name)} for details.
+     *
+     * @param name
+     *		a name relative to this context
+     * @param prefix
+     *		the name of this context relative to one of its ancestors
+     * @return	the composition of <code>prefix</code> and <code>name</code>
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public String composeName(String name, String prefix)
+	    throws NamingException
+    {
+        return m_helper.composeName(name, prefix) ;
+    }
+
+
+    /**
+     * Adds a new environment property to the environment of this
+     * context.  If the property already exists, its value is overwritten.
+     * See class description for more details on environment properties.
+     *
+     * @param propName
+     *		the name of the environment property to add; may not be null
+     * @param propVal
+     *		the value of the property to add; may not be null
+     * @return	the previous value of the property, or null if the property was
+     *		not in the environment before
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #getEnvironment()
+     * @see #removeFromEnvironment(String)
+     */
+    public Object addToEnvironment(String propName, Object propVal)
+     throws NamingException
+    {
+        return m_env.put(propName, propVal) ;
+    }
+
+
+    /**
+     * Removes an environment property from the environment of this
+     * context.  See class description for more details on environment
+     * properties.
+     *
+     * @param propName
+     *		the name of the environment property to remove; may not be null
+     * @return	the previous value of the property, or null if the property was
+     *		not in the environment
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #getEnvironment()
+     * @see #addToEnvironment(String, Object)
+     */
+    public Object removeFromEnvironment(String propName)
+     throws NamingException
+    {
+        return m_env.remove(propName) ;
+    }
+
+
+    /**
+     * Retrieves the environment in effect for this context.
+     * See class description for more details on environment properties.
+     *
+     * <p> The caller should not make any changes to the object returned:
+     * their effect on the context is undefined.
+     * The environment of this context may be changed using
+     * <tt>addToEnvironment()</tt> and <tt>removeFromEnvironment()</tt>.
+     *
+     * @return	the environment of this context; never null
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #addToEnvironment(String, Object)
+     * @see #removeFromEnvironment(String)
+     */
+    public Hashtable getEnvironment() throws NamingException
+    {
+        return this.m_env ;
+    }
+
+
+    /**
+     * Closes this context.
+     * This method releases this context's resources immediately, instead of
+     * waiting for them to be released automatically by the garbage collector.
+     *
+     * <p> This method is idempotent:  invoking it on a context that has
+     * already been closed has no effect.  Invoking any other method
+     * on a closed context is not allowed, and results in undefined behaviour.
+     *
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void close() throws NamingException
+    {
+        // Does nothing for now
+    }
+
+
+    /**
+     * Retrieves the full name of this context within its own namespace.
+     *
+     * <p> Many naming services have a notion of a "full name" for objects
+     * in their respective namespaces.  For example, an LDAP entry has
+     * a distinguished name, and a DNS record has a fully qualified name.
+     * This method allows the client application to retrieve this name.
+     * The string returned by this method is not a JNDI composite name
+     * and should not be passed directly to context methods.
+     * In naming systems for which the notion of full name does not
+     * make sense, <tt>OperationNotSupportedException</tt> is thrown.
+     *
+     * @return	this context's name in its own namespace; never null
+     * @throws	javax.naming.OperationNotSupportedException if the naming system does
+     *		not have the notion of a full name
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @since 1.3
+     */
+    public String getNameInNamespace() throws NamingException
+    {
+        return m_entry.getEntryDN() ;
+    }
+
+
+    public Object clone()
+    {
+        try
+        {
+            // Every context other than the default on the RootDSE will have
+            // a non-zero relative distinguished name.
+            if( m_rdn.size() > 0 )
+            {
+                return new UnifiedLdapContext( m_env, m_entry ) ;
+            }
+    
+            return new UnifiedLdapContext( m_env ) ;
+        }
+        catch( NamingException e )
+        {
+            e.printStackTrace() ;
+            // Should log something here.
+            return null ;
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Package Friendly Methods Used By ContextHelper Class
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the LdapEntry represented by this Context.
+     *
+     * @return this contexts associated LdapEntry
+     */
+    LdapEntry getEntry()
+    {
+        return m_entry ;
+    }
+
+
+    void threadAssociate()
+    {
+        JndiProviderModule l_provider = JndiProviderModule.getInstance() ;
+        ClientManager l_clientManager = l_provider.getClientManager() ;
+
+        // We only want to associate threads that are not protocol module worker
+        // threads.  Protocol module worker threads have client keys so if the
+        // key is null we can associate this thread with the client manager.
+		if( l_clientManager.getClientKey() == null )
+        {
+        	l_clientManager.threadAssociate( ( LdapContext ) this ) ;
+        }
+    }
+
+
+    void threadDisassociate()
+    {
+        JndiProviderModule l_provider = JndiProviderModule.getInstance() ;
+        ClientManager l_clientManager = l_provider.getClientManager() ;
+
+        // We only want to disassociate threads that are not protocol module
+        // worker threads and have registered themselves.  Protocol module
+        // worker threads have client keys so if the key is null we can
+        // disassociate this thread with the client manager.  We also prevent
+        // disassociation if the context has changed.
+
+        // If a cascade of JNDI activity is caused by triggers, synchronous
+        // processing will cause the overright of the first associated context
+        // with Contexts used in trigger bodies.  This is the case if the
+        // trigger fires before an operation occurs.  Once the cascade
+        // is over code relying on Context to be the same will have a handle on
+        // the wrong context.  This is a serious flaw in this design.
+
+        // We could maintain a stack of Contexts on the ClientManager.  When
+        // a thread is associated with a context a check is made to determine
+        // if it already is associated with another context.  If so the old
+        // context is pushed onto the stack and the new context is associated.
+        // Disassociations remove the associated Context and reassociate older
+        // Contexts by popping them off the stack.  This way a cascade before
+        // an operation which may oust the first Context, will reinstate it
+        // when the cascade terminates.
+
+        // Also note that dropping a client will make the key go away and the
+        // JNDI provider will suddenly presume the thread of execution not to be
+        // a protocol module worker thread.  This may completely confuse correct
+        // operation.  At this point I'm seriously reconsidering this facility.
+
+		if( l_clientManager.getClientKey() == null
+            && l_clientManager.getLdapContext() == this )
+        {
+	        l_clientManager.threadDisassociate() ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedDirContext.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedDirContext.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,987 @@
+/*
+ * $Id: UnifiedDirContext.java,v 1.10 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.Name ;
+import javax.naming.Context ;
+import javax.naming.NamingException ;
+import javax.naming.NamingEnumeration ;
+
+import javax.naming.directory.Attributes ;
+import javax.naming.directory.DirContext ;
+import javax.naming.directory.SearchControls ;
+import javax.naming.directory.ModificationItem ;
+
+import org.apache.eve.backend.LdapEntry ;
+
+
+/**
+ * The internal server side LdapContext implementation used to access and
+ * modify server entries.  Most bind operations will be unsupported since
+ * instances of this context are already bound.  This context is the main
+ * class of the internal server side provider.  It is used whenever an
+ * initial context is requested within stored procedures or within a
+ * server trigger.  It is also the basis for server side communication between
+ * a server host with an embedded ldapd server component.  The UnifiedBackend
+ * as well as a public Kernel interface will expose a handle to the RootDSE
+ * using this LdapContext implementation.
+ *
+ * Note that the documentation used by the Java APIs for Context, DirContext
+ * and LdapContext are copied here for convenience.   Eventually we can make
+ * these chunks of javadocs @see references to the respective interfaces.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.10 $
+ */
+public abstract class UnifiedDirContext
+    extends UnifiedContext
+    implements DirContext
+{
+    private final DirContextHelper m_helper ;
+
+
+    protected UnifiedDirContext( Hashtable an_environment )
+    {
+        super( an_environment ) ;
+        m_helper = new DirContextHelper( this ) ;
+    }
+
+
+    protected UnifiedDirContext( Hashtable an_environment, LdapEntry a_entry )
+        throws NamingException
+    {
+        super( an_environment, a_entry ) ;
+        m_helper = new DirContextHelper( this ) ;
+    }
+
+
+    ////////////////////////////////
+    // DirContext Implementations //
+    ////////////////////////////////
+
+
+    /**
+     * Retrieves all of the attributes associated with a named object.
+     * See the class description regarding attribute models, attribute
+     * type names, and operational attributes.
+     *
+     * @param name
+     *		the name of the object from which to retrieve attributes
+     * @return	the set of attributes associated with <code>name</code>.
+     *		Returns an empty attribute set if name has no attributes;
+     *		never null.
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #getAttributes(String)
+     * @see #getAttributes(Name, String[])
+     */
+    public Attributes getAttributes(Name name) throws NamingException
+    {
+        return m_helper.getAttributes(name) ;
+    }
+
+
+    /**
+     * Retrieves all of the attributes associated with a named object.
+     * See {@link #getAttributes(Name)} for details.
+     *
+     * @param name
+     *		the name of the object from which to retrieve attributes
+     * @return	the set of attributes associated with <code>name</code>
+     *
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Attributes getAttributes(String name) throws NamingException
+    {
+        return m_helper.getAttributes(name) ;
+    }
+
+
+    /**
+     * Retrieves selected attributes associated with a named object.
+     * See the class description regarding attribute models, attribute
+     * type names, and operational attributes.
+     *
+     * <p> If the object does not have an attribute
+     * specified, the directory will ignore the nonexistent attribute
+     * and return those requested attributes that the object does have.
+     *
+     * <p> A directory might return more attributes than was requested
+     * (see <strong>Attribute Type Names</strong> in the class description),
+     * but is not allowed to return arbitrary, unrelated attributes.
+     *
+     * <p> See also <strong>Operational Attributes</strong> in the class
+     * description.
+     *
+     * @param name
+     *		the name of the object from which to retrieve attributes
+     * @param attrIds
+     *		the identifiers of the attributes to retrieve.
+     * 		null indicates that all attributes should be retrieved;
+     *     	an empty array indicates that none should be retrieved.
+     * @return	the requested attributes; never null
+     *
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Attributes getAttributes(Name name, String[] attrIds)
+	    throws NamingException
+    {
+        return m_helper.getAttributes(name, attrIds) ;
+    }
+
+
+    /**
+     * Retrieves selected attributes associated with a named object.
+     * See {@link #getAttributes(Name, String[])} for details.
+     *
+     * @param name
+     *		The name of the object from which to retrieve attributes
+     * @param attrIds
+     *		the identifiers of the attributes to retrieve.
+     * 		null indicates that all attributes should be retrieved;
+     *     	an empty array indicates that none should be retrieved.
+     * @return	the requested attributes; never null
+     *
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public Attributes getAttributes(String name, String[] attrIds)
+	    throws NamingException
+    {
+        return m_helper.getAttributes(name, attrIds) ;
+    }
+
+
+    /**
+     * Modifies the attributes associated with a named object.
+     * The order of the modifications is not specified.  Where
+     * possible, the modifications are performed atomically.
+     *
+     * @param name
+     *		the name of the object whose attributes will be updated
+     * @param mod_op
+     *		the modification operation, one of:
+     *			<code>ADD_ATTRIBUTE</code>,
+     *			<code>REPLACE_ATTRIBUTE</code>,
+     *			<code>REMOVE_ATTRIBUTE</code>.
+     * @param attrs
+     *		the attributes to be used for the modification; may not be null
+     *
+     * @throws	javax.naming.directory.AttributeModificationException if the modification cannot
+     *		be completed successfully
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #modifyAttributes(Name, ModificationItem[])
+     */
+    public void modifyAttributes(Name name, int mod_op, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.modifyAttributes(name, mod_op, attrs) ;
+    }
+
+
+    /**
+     * Modifies the attributes associated with a named object.
+     * See {@link #modifyAttributes(Name, int, Attributes)} for details.
+     *
+     * @param name
+     *		the name of the object whose attributes will be updated
+     * @param mod_op
+     *		the modification operation, one of:
+     *			<code>ADD_ATTRIBUTE</code>,
+     *			<code>REPLACE_ATTRIBUTE</code>,
+     *			<code>REMOVE_ATTRIBUTE</code>.
+     * @param attrs
+     *		the attributes to be used for the modification; map not be null
+     *
+     * @throws	javax.naming.directory.AttributeModificationException if the modification cannot
+     *		be completed successfully
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void modifyAttributes(String name, int mod_op, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.modifyAttributes(name, mod_op, attrs) ;
+    }
+
+
+    /**
+     * Modifies the attributes associated with a named object using
+     * an ordered list of modifications.
+     * The modifications are performed
+     * in the order specified.  Each modification specifies a
+     * modification operation code and an attribute on which to
+     * operate.  Where possible, the modifications are
+     * performed atomically.
+     *
+     * @param name
+     *		the name of the object whose attributes will be updated
+     * @param mods
+     *		an ordered sequence of modifications to be performed;
+     *		may not be null
+     *
+     * @throws	javax.naming.directory.AttributeModificationException if the modifications
+     *		cannot be completed successfully
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #modifyAttributes(Name, int, Attributes)
+     * @see <{ModificationItem}>
+     */
+    public void modifyAttributes(Name name, ModificationItem[] mods)
+	    throws NamingException
+    {
+        m_helper.modifyAttributes(name, mods) ;
+    }
+
+
+    /**
+     * Modifies the attributes associated with a named object using
+     * an ordered list of modifications.
+     * See {@link #modifyAttributes(Name, ModificationItem[])} for details.
+     *
+     * @param name
+     *		the name of the object whose attributes will be updated
+     * @param mods
+     *		an ordered sequence of modifications to be performed;
+     *		may not be null
+     *
+     * @throws	javax.naming.directory.AttributeModificationException if the modifications
+     *		cannot be completed successfully
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void modifyAttributes(String name, ModificationItem[] mods)
+	    throws NamingException
+    {
+        m_helper.modifyAttributes(name, mods) ;
+    }
+
+
+    /**
+     * Binds a name to an object, along with associated attributes.
+     * If <tt>attrs</tt> is null, the resulting binding will have
+     * the attributes associated with <tt>obj</tt> if <tt>obj</tt> is a
+     * <tt>DirContext</tt>, and no attributes otherwise.
+     * If <tt>attrs</tt> is non-null, the resulting binding will have
+     * <tt>attrs</tt> as its attributes; any attributes associated with
+     * <tt>obj</tt> are ignored.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @param attrs
+     *		the attributes to associate with the binding
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException if some "mandatory" attributes
+     *		of the binding are not supplied
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see Context#bind(Name, Object)
+     * @see #rebind(Name, Object, Attributes)
+     */
+    public void bind(Name name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.bind(name, obj, attrs) ;
+    }
+
+
+    /**
+     * Binds a name to an object, along with associated attributes.
+     * See {@link #bind(Name, Object, Attributes)} for details.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @param attrs
+     *		the attributes to associate with the binding
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException if some "mandatory" attributes
+     *		of the binding are not supplied
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void bind(String name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.bind(name, obj, attrs) ;
+    }
+
+
+    /**
+     * Binds a name to an object, along with associated attributes,
+     * overwriting any existing binding.
+     * If <tt>attrs</tt> is null and <tt>obj</tt> is a <tt>DirContext</tt>,
+     * the attributes from <tt>obj</tt> are used.
+     * If <tt>attrs</tt> is null and <tt>obj</tt> is not a <tt>DirContext</tt>,
+     * any existing attributes associated with the object already bound
+     * in the directory remain unchanged.
+     * If <tt>attrs</tt> is non-null, any existing attributes associated with
+     * the object already bound in the directory are removed and <tt>attrs</tt>
+     * is associated with the named object.  If <tt>obj</tt> is a
+     * <tt>DirContext</tt> and <tt>attrs</tt> is non-null, the attributes
+     * of <tt>obj</tt> are ignored.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @param attrs
+     *		the attributes to associate with the binding
+     *
+     * @throws	javax.naming.directory.InvalidAttributesException if some "mandatory" attributes
+     *		of the binding are not supplied
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see Context#bind(Name, Object)
+     * @see #bind(Name, Object, Attributes)
+     */
+    public void rebind(Name name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.rebind(name, obj, attrs) ;
+    }
+
+
+    /**
+     * Binds a name to an object, along with associated attributes,
+     * overwriting any existing binding.
+     * See {@link #rebind(Name, Object, Attributes)} for details.
+     *
+     * @param name
+     *		the name to bind; may not be empty
+     * @param obj
+     *		the object to bind; possibly null
+     * @param attrs
+     *		the attributes to associate with the binding
+     *
+     * @throws	javax.naming.directory.InvalidAttributesException if some "mandatory" attributes
+     *		of the binding are not supplied
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public void rebind(String name, Object obj, Attributes attrs)
+	    throws NamingException
+    {
+        m_helper.rebind(name, obj, attrs) ;
+    }
+
+
+    /**
+     * Creates and binds a new context, along with associated attributes.
+     * This method creates a new subcontext with the given name, binds it in
+     * the target context (that named by all but terminal atomic
+     * component of the name), and associates the supplied attributes
+     * with the newly created object.
+     * All intermediate and target contexts must already exist.
+     * If <tt>attrs</tt> is null, this method is equivalent to
+     * <tt>Context.createSubcontext()</tt>.
+     *
+     * @param a_name
+     *		the name of the context to create; may not be empty
+     * @param a_attrs
+     *		the attributes to associate with the newly created context
+     * @return	the newly created context
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if the name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException if <code>attrs</code> does not
+     *		contain all the mandatory attributes required for creation
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see Context#createSubcontext(Name)
+     */
+    public DirContext createSubcontext( Name a_name, Attributes a_attrs )
+	    throws NamingException
+    {
+        return m_helper.createSubcontext( a_name, a_attrs) ;
+    }
+
+
+    /**
+     * Creates and binds a new context, along with associated attributes.
+     * See {@link #createSubcontext(Name, Attributes)} for details.
+     *
+     * @param a_name
+     *		the name of the context to create; may not be empty
+     * @param a_attrs
+     *		the attributes to associate with the newly created context
+     * @return	the newly created context
+     *
+     * @throws	javax.naming.NameAlreadyBoundException if the name is already bound
+     * @throws	javax.naming.directory.InvalidAttributesException if <code>attrs</code> does not
+     *		contain all the mandatory attributes required for creation
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public DirContext createSubcontext( String a_name, Attributes a_attrs )
+	    throws NamingException
+    {
+        return m_helper.createSubcontext( a_name, a_attrs ) ;
+    }
+
+
+    ///////////////////////
+    // Schema Operations //
+    ///////////////////////
+
+
+    /**
+     * Retrieves the schema associated with the named object.
+     * The schema describes rules regarding the structure of the namespace
+     * and the attributes stored within it.  The schema
+     * specifies what types of objects can be added to the directory and where
+     * they can be added; what mandatory and optional attributes an object
+     * can have. The range of support for schemas is directory-specific.
+     *
+     * <p> This method returns the root of the schema information tree
+     * that is applicable to the named object. Several named objects
+     * (or even an entire directory) might share the same schema.
+     *
+     * <p> Issues such as structure and contents of the schema tree,
+     * permission to modify to the contents of the schema
+     * tree, and the effect of such modifications on the directory
+     * are dependent on the underlying directory.
+     *
+     * @param name
+     *		the name of the object whose schema is to be retrieved
+     * @return	the schema associated with the context; never null
+     * @throws	javax.naming.OperationNotSupportedException if schema not supported
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public DirContext getSchema(Name name) throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the schema associated with the named object.
+     * See {@link #getSchema(Name)} for details.
+     *
+     * @param name
+     *		the name of the object whose schema is to be retrieved
+     * @return	the schema associated with the context; never null
+     * @throws	javax.naming.OperationNotSupportedException if schema not supported
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public DirContext getSchema(String name) throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves a context containing the schema objects of the
+     * named object's class definitions.
+     *<p>
+     * One category of information found in directory schemas is
+     * <em>class definitions</em>.  An "object class" definition
+     * specifies the object's <em>type</em> and what attributes (mandatory
+     * and optional) the object must/can have. Note that the term
+     * "object class" being referred to here is in the directory sense
+     * rather than in the Java sense.
+     * For example, if the named object is a directory object of
+     * "Person" class, <tt>getSchemaClassDefinition()</tt> would return a
+     * <tt>DirContext</tt> representing the (directory's) object class
+     * definition of "Person".
+     *<p>
+     * The information that can be retrieved from an object class definition
+     * is directory-dependent.
+     *<p>
+     * Prior to JNDI 1.2, this method
+     * returned a single schema object representing the class definition of
+     * the named object.
+     * Since JNDI 1.2, this method returns a <tt>DirContext</tt> containing
+     * all of the named object's class definitions.
+     *
+     * @param name
+     *		the name of the object whose object class
+     *		definition is to be retrieved
+     * @return	the <tt>DirContext</tt> containing the named
+     *		object's class definitions; never null
+     *
+     * @throws	javax.naming.OperationNotSupportedException if schema not supported
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public DirContext getSchemaClassDefinition(Name name)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves a context containing the schema objects of the
+     * named object's class definitions.
+     * See {@link #getSchemaClassDefinition(Name)} for details.
+     *
+     * @param name
+     *		the name of the object whose object class
+     *		definition is to be retrieved
+     * @return	the <tt>DirContext</tt> containing the named
+     *		object's class definitions; never null
+     *
+     * @throws	javax.naming.OperationNotSupportedException if schema not supported
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public DirContext getSchemaClassDefinition(String name)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    ///////////////////////
+    // Search Operations //
+    ///////////////////////
+
+
+    /**
+     * Searches in a single context for objects that contain a
+     * specified set of attributes, and retrieves selected attributes.
+     * The search is performed using the default
+     * <code>SearchControls</code> settings.
+     * <p>
+     * For an object to be selected, each attribute in
+     * <code>matchingAttributes</code> must match some attribute of the
+     * object.  If <code>matchingAttributes</code> is empty or
+     * null, all objects in the target context are returned.
+     *<p>
+     * An attribute <em>A</em><sub>1</sub> in
+     * <code>matchingAttributes</code> is considered to match an
+     * attribute <em>A</em><sub>2</sub> of an object if
+     * <em>A</em><sub>1</sub> and <em>A</em><sub>2</sub> have the same
+     * identifier, and each value of <em>A</em><sub>1</sub> is equal
+     * to some value of <em>A</em><sub>2</sub>.  This implies that the
+     * order of values is not significant, and that
+     * <em>A</em><sub>2</sub> may contain "extra" values not found in
+     * <em>A</em><sub>1</sub> without affecting the comparison.  It
+     * also implies that if <em>A</em><sub>1</sub> has no values, then
+     * testing for a match is equivalent to testing for the presence
+     * of an attribute <em>A</em><sub>2</sub> with the same
+     * identifier.
+     *<p>
+     * The precise definition of "equality" used in comparing attribute values
+     * is defined by the underlying directory service.  It might use the
+     * <code>Object.equals</code> method, for example, or might use a schema
+     * to specify a different equality operation.
+     * For matching based on operations other than equality (such as
+     * substring comparison) use the version of the <code>search</code>
+     * method that takes a filter argument.
+     * <p>
+     * When changes are made to this <tt>DirContext</tt>,
+     * the effect on enumerations returned by prior calls to this method
+     * is undefined.
+     *<p>
+     * If the object does not have the attribute
+     * specified, the directory will ignore the nonexistent attribute
+     * and return the requested attributes that the object does have.
+     *<p>
+     * A directory might return more attributes than was requested
+     * (see <strong>Attribute Type Names</strong> in the class description),
+     * but is not allowed to return arbitrary, unrelated attributes.
+     *<p>
+     * See also <strong>Operational Attributes</strong> in the class
+     * description.
+     *
+     * @param name
+     *		the name of the context to search
+     * @param matchingAttributes
+     *		the attributes to search for.  If empty or null,
+     *		all objects in the target context are returned.
+     * @param attributesToReturn
+     *		the attributes to return.  null indicates that
+     *		all attributes are to be returned;
+     *		an empty array indicates that none are to be returned.
+     * @return
+     *		a non-null enumeration of <tt>SearchResult</tt> objects.
+     *		Each <tt>SearchResult</tt> contains the attributes
+     *		identified by <code>attributesToReturn</code>
+     *		and the name of the corresponding object, named relative
+     * 		to the context named by <code>name</code>.
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see <{SearchControls}>
+     * @see javax.naming.directory.SearchResult
+     * @see #search(Name, String, Object[], SearchControls)
+     */
+    public NamingEnumeration search(Name name,
+	                Attributes matchingAttributes,
+	                String[] attributesToReturn)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in a single context for objects that contain a
+     * specified set of attributes, and retrieves selected attributes.
+     * See {@link #search(Name, Attributes, String[])} for details.
+     *
+     * @param name
+     *		the name of the context to search
+     * @param matchingAttributes
+     *		the attributes to search for
+     * @param attributesToReturn
+     *		the attributes to return
+     * @return	a non-null enumeration of <tt>SearchResult</tt> objects
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration search(String name,
+	                Attributes matchingAttributes,
+	                String[] attributesToReturn)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in a single context for objects that contain a
+     * specified set of attributes.
+     * This method returns all the attributes of such objects.
+     * It is equivalent to supplying null as
+     * the <tt>atributesToReturn</tt> parameter to the method
+     * <code>search(Name, Attributes, String[])</code>.
+     * <br>
+     * See {@link #search(Name, Attributes, String[])} for a full description.
+     *
+     * @param name
+     *		the name of the context to search
+     * @param matchingAttributes
+     *		the attributes to search for
+     * @return	an enumeration of <tt>SearchResult</tt> objects
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #search(Name, Attributes, String[])
+     */
+    public NamingEnumeration search(Name name,
+	                Attributes matchingAttributes)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in a single context for objects that contain a
+     * specified set of attributes.
+     * See {@link #search(Name, Attributes)} for details.
+     *
+     * @param name
+     *		the name of the context to search
+     * @param matchingAttributes
+     *		the attributes to search for
+     * @return	an enumeration of <tt>SearchResult</tt> objects
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration search(String name,
+	                Attributes matchingAttributes)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in the named context or object for entries that satisfy the
+     * given search filter.  Performs the search as specified by
+     * the search controls.
+     * <p>
+     * The format and interpretation of <code>filter</code> follows RFC 2254
+     * with the
+     * following interpretations for <code>attr</code> and <code>value</code>
+     * mentioned in the RFC.
+     * <p>
+     * <code>attr</code> is the attribute's identifier.
+     * <p>
+     * <code>value</code> is the string representation the attribute's value.
+     * The translation of this string representation into the attribute's value
+     * is directory-specific.
+     * <p>
+     * For the assertion "someCount=127", for example, <code>attr</code>
+     * is "someCount" and <code>value</code> is "127".
+     * The provider determines, based on the attribute ID ("someCount")
+     * (and possibly its schema), that the attribute's value is an integer.
+     * It then parses the string "127" appropriately.
+     *<p>
+     * Any non-ASCII characters in the filter string should be
+     * represented by the appropriate Java (Unicode) characters, and
+     * not encoded as UTF-8 octets.  Alternately, the
+     * "backslash-hexcode" notation described in RFC 2254 may be used.
+     *<p>
+     * If the directory does not support a string representation of
+     * some or all of its attributes, the form of <code>search</code> that
+     * accepts filter arguments in the form of Objects can be used instead.
+     * The service provider for such a directory would then translate
+     * the filter arguments to its service-specific representation
+     * for filter evaluation.
+     * See <code>search(Name, String, Object[], SearchControls)</code>.
+     * <p>
+     * RFC 2254 defines certain operators for the filter, including substring
+     * matches, equality, approximate match, greater than, less than.  These
+     * operators are mapped to operators with corresponding semantics in the
+     * underlying directory. For example, for the equals operator, suppose
+     * the directory has a matching rule defining "equality" of the
+     * attributes in the filter. This rule would be used for checking
+     * equality of the attributes specified in the filter with the attributes
+     * of objects in the directory. Similarly, if the directory has a
+     * matching rule for ordering, this rule would be used for
+     * making "greater than" and "less than" comparisons.
+     *<p>
+     * Not all of the operators defined in RFC 2254 are applicable to all
+     * attributes.  When an operator is not applicable, the exception
+     * <code>InvalidSearchFilterException</code> is thrown.
+     * <p>
+     * The result is returned in an enumeration of <tt>SearchResult</tt>s.
+     * Each <tt>SearchResult</tt> contains the name of the object
+     * and other information about the object (see SearchResult).
+     * The name is either relative to the target context of the search
+     * (which is named by the <code>name</code> parameter), or
+     * it is a URL string. If the target context is included in
+     * the enumeration (as is possible when
+     * <code>cons</code> specifies a search scope of
+     * <code>SearchControls.OBJECT_SCOPE</code> or
+     * <code>SearchControls.SUBSTREE_SCOPE</code>), its name is the empty
+     * string. The <tt>SearchResult</tt> may also contain attributes of the
+     * matching object if the <tt>cons</tt> argument specified that attributes
+     * be returned.
+     *<p>
+     * If the object does not have a requested attribute, that
+     * nonexistent attribute will be ignored.  Those requested
+     * attributes that the object does have will be returned.
+     *<p>
+     * A directory might return more attributes than were requested
+     * (see <strong>Attribute Type Names</strong> in the class description)
+     * but is not allowed to return arbitrary, unrelated attributes.
+     *<p>
+     * See also <strong>Operational Attributes</strong> in the class
+     * description.
+     *
+     * @param name
+     *		the name of the context or object to search
+     * @param filter
+     *		the filter expression to use for the search; may not be null
+     * @param cons
+     *		the search controls that control the search.  If null,
+     *		the default search controls are used (equivalent
+     *		to <tt>(new SearchControls())</tt>).
+     * @return	an enumeration of <tt>SearchResult</tt>s of
+     * 		the objects that satisfy the filter; never null
+     *
+     * @throws	javax.naming.directory.InvalidSearchFilterException if the search filter specified is
+     *		not supported or understood by the underlying directory
+     * @throws	javax.naming.directory.InvalidSearchControlsException if the search controls
+     * 		contain invalid settings
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #search(Name, String, Object[], SearchControls)
+     * @see <{SearchControls}>
+     * @see javax.naming.directory.SearchResult
+     */
+    public NamingEnumeration search(Name name,
+	                String filter,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in the named context or object for entries that satisfy the
+     * given search filter.  Performs the search as specified by
+     * the search controls.
+     * See {@link #search(Name, String, SearchControls)} for details.
+     *
+     * @param name
+     *		the name of the context or object to search
+     * @param filter
+     *		the filter expression to use for the search; may not be null
+     * @param cons
+     *		the search controls that control the search.  If null,
+     *		the default search controls are used (equivalent
+     *		to <tt>(new SearchControls())</tt>).
+     *
+     * @return	an enumeration of <tt>SearchResult</tt>s for
+     * 		the objects that satisfy the filter.
+     * @throws	javax.naming.directory.InvalidSearchFilterException if the search filter specified is
+     *		not supported or understood by the underlying directory
+     * @throws	javax.naming.directory.InvalidSearchControlsException if the search controls
+     * 		contain invalid settings
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration search(String name,
+	                String filter,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in the named context or object for entries that satisfy the
+     * given search filter.  Performs the search as specified by
+     * the search controls.
+     *<p>
+     * The interpretation of <code>filterExpr</code> is based on RFC
+     * 2254.  It may additionally contain variables of the form
+     * <code>{i}</code> -- where <code>i</code> is an integer -- that
+     * refer to objects in the <code>filterArgs</code> array.  The
+     * interpretation of <code>filterExpr</code> is otherwise
+     * identical to that of the <code>filter</code> parameter of the
+     * method <code>search(Name, String, SearchControls)</code>.
+     *<p>
+     * When a variable <code>{i}</code> appears in a search filter, it
+     * indicates that the filter argument <code>filterArgs[i]</code>
+     * is to be used in that place.  Such variables may be used
+     * wherever an <em>attr</em>, <em>value</em>, or
+     * <em>matchingrule</em> production appears in the filter grammar
+     * of RFC 2254, section 4.  When a string-valued filter argument
+     * is substituted for a variable, the filter is interpreted as if
+     * the string were given in place of the variable, with any
+     * characters having special significance within filters (such as
+     * <code>'*'</code>) having been escaped according to the rules of
+     * RFC 2254.
+     *<p>
+     * For directories that do not use a string representation for
+     * some or all of their attributes, the filter argument
+     * corresponding to an attribute value may be of a type other than
+     * String.  Directories that support unstructured binary-valued
+     * attributes, for example, should accept byte arrays as filter
+     * arguments.  The interpretation (if any) of filter arguments of
+     * any other type is determined by the service provider for that
+     * directory, which maps the filter operations onto operations with
+     * corresponding semantics in the underlying directory.
+     *<p>
+     * This method returns an enumeration of the results.
+     * Each element in the enumeration contains the name of the object
+     * and other information about the object (see <code>SearchResult</code>).
+     * The name is either relative to the target context of the search
+     * (which is named by the <code>name</code> parameter), or
+     * it is a URL string. If the target context is included in
+     * the enumeration (as is possible when
+     * <code>cons</code> specifies a search scope of
+     * <code>SearchControls.OBJECT_SCOPE</code> or
+     * <code>SearchControls.SUBSTREE_SCOPE</code>),
+     * its name is the empty string.
+     *<p>
+     * The <tt>SearchResult</tt> may also contain attributes of the matching
+     * object if the <tt>cons</tt> argument specifies that attributes be
+     * returned.
+     *<p>
+     * If the object does not have a requested attribute, that
+     * nonexistent attribute will be ignored.  Those requested
+     * attributes that the object does have will be returned.
+     *<p>
+     * A directory might return more attributes than were requested
+     * (see <strong>Attribute Type Names</strong> in the class description)
+     * but is not allowed to return arbitrary, unrelated attributes.
+     *<p>
+     * If a search filter with invalid variable substitutions is provided
+     * to this method, the result is undefined.
+     * When changes are made to this DirContext,
+     * the effect on enumerations returned by prior calls to this method
+     * is undefined.
+     *<p>
+     * See also <strong>Operational Attributes</strong> in the class
+     * description.
+     *
+     * @param name
+     *		the name of the context or object to search
+     * @param filterExpr
+     *		the filter expression to use for the search.
+     *		The expression may contain variables of the
+     *		form "<code>{i}</code>" where <code>i</code>
+     *		is a nonnegative integer.  May not be null.
+     * @param filterArgs
+     *		the array of arguments to substitute for the variables
+     *		in <code>filterExpr</code>.  The value of
+     *		<code>filterArgs[i]</code> will replace each
+     *		occurrence of "<code>{i}</code>".
+     *		If null, equivalent to an empty array.
+     * @param cons
+     *		the search controls that control the search.  If null,
+     *		the default search controls are used (equivalent
+     *		to <tt>(new SearchControls())</tt>).
+     * @return	an enumeration of <tt>SearchResult</tt>s of the objects
+     *		that satisfy the filter; never null
+     *
+     * @throws	ArrayIndexOutOfBoundsException if <tt>filterExpr</tt> contains
+     *		<code>{i}</code> expressions where <code>i</code> is outside
+     *		the bounds of the array <code>filterArgs</code>
+     * @throws	javax.naming.directory.InvalidSearchControlsException if <tt>cons</tt> contains
+     *		invalid settings
+     * @throws	javax.naming.directory.InvalidSearchFilterException if <tt>filterExpr</tt> with
+     *		<tt>filterArgs</tt> represents an invalid search filter
+     * @throws	NamingException if a naming exception is encountered
+     *
+     * @see #search(Name, Attributes, String[])
+     * @see <{MessageFormat}>
+     */
+    public NamingEnumeration search(Name name,
+	                String filterExpr,
+	                Object[] filterArgs,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Searches in the named context or object for entries that satisfy the
+     * given search filter.  Performs the search as specified by
+     * the search controls.
+     * See {@link #search(Name, String, Object[], SearchControls)} for details.
+     *
+     * @param name
+     *		the name of the context or object to search
+     * @param filterExpr
+     *		the filter expression to use for the search.
+     *		The expression may contain variables of the
+     *		form "<code>{i}</code>" where <code>i</code>
+     *		is a nonnegative integer.  May not be null.
+     * @param filterArgs
+     *		the array of arguments to substitute for the variables
+     *		in <code>filterExpr</code>.  The value of
+     *		<code>filterArgs[i]</code> will replace each
+     *		occurrence of "<code>{i}</code>".
+     *		If null, equivalent to an empty array.
+     * @param cons
+     *		the search controls that control the search.  If null,
+     *		the default search controls are used (equivalent
+     *		to <tt>(new SearchControls())</tt>).
+     * @return	an enumeration of <tt>SearchResult</tt>s of the objects
+     *		that satisfy the filter; never null
+     *
+     * @throws	ArrayIndexOutOfBoundsException if <tt>filterExpr</tt> contains
+     *		<code>{i}</code> expressions where <code>i</code> is outside
+     *		the bounds of the array <code>filterArgs</code>
+     * @throws	javax.naming.directory.InvalidSearchControlsException if <tt>cons</tt> contains
+     *		invalid settings
+     * @throws	javax.naming.directory.InvalidSearchFilterException if <tt>filterExpr</tt> with
+     *		<tt>filterArgs</tt> represents an invalid search filter
+     * @throws	NamingException if a naming exception is encountered
+     */
+    public NamingEnumeration search(String name,
+	                String filterExpr,
+	                Object[] filterArgs,
+	                SearchControls cons)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedLdapContext.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/jndi/UnifiedLdapContext.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,245 @@
+/*
+ * $Id: UnifiedLdapContext.java,v 1.4 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.jndi ;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.NamingException ;
+import javax.naming.ldap.Control ;
+import javax.naming.ldap.LdapContext ;
+import javax.naming.ldap.ExtendedRequest ;
+import javax.naming.ldap.ExtendedResponse ;
+
+import org.apache.eve.backend.LdapEntry ;
+
+
+/**
+ * The internal server side LdapContext implementation used to access and
+ * modify server entries.  Most bind operations will be unsupported since
+ * instances of this context are already bound.  This context is the main
+ * class of the internal server side provider.  It is used whenever an
+ * initial context is requested within stored procedures or within a
+ * server trigger.  It is also the basis for server side communication between
+ * a server host with an embedded ldapd server component.  The UnifiedBackend
+ * as well as a public Kernel interface will expose a handle to the RootDSE
+ * using this LdapContext implementation.
+ *
+ * Note that the documentation used by the Java APIs for Context, DirContext
+ * and LdapContext are copied here for convenience.   Eventually we can make
+ * these chunks of javadocs @see references to the respective interfaces.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.4 $
+ */
+public class UnifiedLdapContext
+    extends UnifiedDirContext
+    implements LdapContext
+{
+    UnifiedLdapContext( Hashtable an_environment )
+    {
+        super( an_environment ) ;
+    }
+
+
+    UnifiedLdapContext( Hashtable an_environment, LdapEntry a_entry )
+        throws NamingException
+    {
+        super( an_environment, a_entry ) ;
+    }
+
+
+    /////////////////////////////////
+    // LdapContext Implementations //
+    /////////////////////////////////
+
+
+   /**
+    * Performs an extended operation.
+    *
+    * This method is used to support LDAPv3 extended operations.
+    * @param request The non-null request to be performed.
+    * @return The possibly null response of the operation. null means
+    * the operation did not generate any response.
+    * @throws NamingException If an error occurred while performing the
+    * extended operation.
+    */
+    public ExtendedResponse extendedOperation(ExtendedRequest request)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Creates a new instance of this context initialized using request controls.
+     *
+     * This method is a convenience method for creating a new instance
+     * of this context for the purposes of multithreaded access.
+     * For example, if multiple threads want to use different context
+     * request controls,
+     * each thread may use this method to get its own copy of this context
+     * and set/get context request controls without having to synchronize with other 
+     * threads.
+     *<p>
+     * The new context has the same environment properties and connection 
+     * request controls as this context. See the class description for details.
+     * Implementations might also allow this context and the new context
+     * to share the same network connection or other resources if doing 
+     * so does not impede the independence of either context.
+     *
+     * @param requestControls The possibly null request controls 
+     * to use for the new context.
+     * If null, the context is initialized with no request controls.
+     *
+     * @return A non-null <tt>LdapContext</tt> instance.
+     * @exception NamingException If an error occurred while creating
+     * the new instance.
+     * @see javax.naming.ldap.InitialLdapContext
+     */
+    public LdapContext newInstance(Control[] requestControls)
+	    throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Reconnects to the LDAP server using the supplied controls and 
+     * this context's environment.
+     *<p>
+     * This method is a way to explicitly initiate an LDAP "bind" operation.
+     * For example, you can use this method to set request controls for
+     * the LDAP "bind" operation, or to explicitly connect to the server 
+     * to get response controls returned by the LDAP "bind" operation.
+     *<p>
+     * This method sets this context's <tt>connCtls</tt>
+     * to be its new connection request controls. This context's
+     * context request controls are not affected.
+     * After this method has been invoked, any subsequent 
+     * implicit reconnections will be done using <tt>connCtls</tt>.
+     * <tt>connCtls</tt> are also used as
+     * connection request controls for new context instances derived from this
+     * context.
+     * These connection request controls are not
+     * affected by <tt>setRequestControls()</tt>.
+     *<p>
+     * Service provider implementors should read the "Service Provider" section
+     * in the class description for implementation details.
+     * @param connCtls The possibly null controls to use. If null, no
+     * controls are used.
+     * @exception NamingException If an error occurred while reconnecting.
+     * @see #getConnectControls
+     * @see #newInstance
+     */
+    public void reconnect(Control[] connCtls) throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the connection request controls in effect for this context.
+     * The controls are owned by the JNDI implementation and are
+     * immutable. Neither the array nor the controls may be modified by the
+     * caller.
+     *
+     * @return A possibly-null array of controls. null means no connect controls
+     * have been set for this context.
+     * @exception NamingException If an error occurred while getting the request
+     * controls.
+     */
+    public Control[] getConnectControls() throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Sets the request controls for methods subsequently 
+     * invoked on this context.
+     * The request controls are owned by the JNDI implementation and are
+     * immutable. Neither the array nor the controls may be modified by the
+     * caller.
+     * <p>
+     * This removes any previous request controls and adds
+     * <tt>requestControls</tt> 
+     * for use by subsequent methods invoked on this context.
+     * This method does not affect this context's connection request controls.
+     *<p>
+     * Note that <tt>requestControls</tt> will be in effect until the next
+     * invocation of <tt>setRequestControls()</tt>. You need to explicitly
+     * invoke <tt>setRequestControls()</tt> with <tt>null</tt> or an empty
+     * array to clear the controls if you don't want them to affect the
+     * context methods any more.
+     * To check what request controls are in effect for this context, use
+     * <tt>getRequestControls()</tt>.
+     * @param requestControls The possibly null controls to use. If null, no
+     * controls are used.
+     * @exception NamingException If an error occurred while setting the
+     * request controls.
+     * @see #getRequestControls
+     */
+    public void setRequestControls(Control[] requestControls)
+    	throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the request controls in effect for this context.
+     * The request controls are owned by the JNDI implementation and are
+     * immutable. Neither the array nor the controls may be modified by the
+     * caller.
+     *
+     * @return A possibly-null array of controls. null means no request controls
+     * have been set for this context.
+     * @exception NamingException If an error occurred while getting the request
+     * controls.
+     * @see #setRequestControls
+     */
+    public Control[] getRequestControls() throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+
+
+    /**
+     * Retrieves the response controls produced as a result of the last
+     * method invoked on this context.
+     * The response controls are owned by the JNDI implementation and are
+     * immutable. Neither the array nor the controls may be modified by the
+     * caller.
+     *<p>
+     * These response controls might have been generated by a successful or
+     * failed operation.
+     *<p>
+     * When a context method that may return response controls is invoked,
+     * response controls from the previous method invocation are cleared.
+     * <tt>getResponseControls()</tt> returns all of the response controls
+     * generated by LDAP operations used by the context method in the order
+     * received from the LDAP server.
+     * Invoking <tt>getResponseControls()</tt> does not
+     * clear the response controls. You can call it many times (and get
+     * back the same controls) until the next context method that may return
+     * controls is invoked.
+     *<p>
+     * @return A possibly null array of controls. If null, the previous
+     * method invoked on this context did not produce any controls.
+     * @exception NamingException If an error occurred while getting the response
+     * controls.
+     */
+    public Control[] getResponseControls() throws NamingException
+    {
+        throw new UnsupportedOperationException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: ListenerException.java,v 1.3 2003/03/13 18:27:38 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.listener ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/** This exception is thrown when protocol errors occurred */
+public class ListenerException extends CascadingRuntimeException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ListenerException(String message, Throwable t)
+    {
+        super(message, t) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ListenerException(String message)
+    {
+        super(message, null) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ListenerModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,298 @@
+/*
+ * $Id: ListenerModule.java,v 1.5 2003/03/13 18:27:38 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.listener ;
+
+
+import java.io.IOException ;
+
+import java.net.Socket ;
+import java.net.InetAddress ;
+import java.net.ServerSocket ;
+import java.net.UnknownHostException ;
+
+import java.io.IOException ;
+
+import java.net.Socket ;
+import java.net.InetAddress ;
+import java.net.ServerSocket ;
+import java.net.UnknownHostException ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.event.ConnectEvent ;
+import org.apache.eve.client.ClientManager ;
+
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.cornerstone.services.threads.ThreadManager ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+
+/**
+ * A server listener module represents a single server socket bound listening
+ * for client connections on a tcp port off an interface.  This implementation
+ * is rather primitive in that only one server socket is used for the entire
+ * module.  In the near future expect the implementation to support multiple
+ * server sockets and to optionally sepecify whether SSL is used.
+ * 
+ * @phoenix:block
+ * @phoenix:mx-topic name="ListenerModule"
+ * @phoenix:service name="org.apache.eve.listener.ServerListener"
+ */
+public class ListenerModule
+    extends AbstractModule
+    implements ServerListener, Runnable
+{
+    /** config.xml tag name for port number to listen to */
+    public static final String PORT_TAG = "port" ;
+    /** config.xml tag name for the ip interface (or hostname) to listen on */
+    public static final String HOST_TAG = "host" ;
+    /** config.xml tag name for the server socket connection backlog */
+	public static final String BACKLOG_TAG = "backlog" ;
+
+    /** default tcp port to listen on (389) */
+    public static final int DEFAULT_PORT = 389 ;
+    /** default server socket backlog (50) */
+    public static final int DEFAULT_BACKLOG = 50 ;
+    /** default interface to listen on (localhost) */
+    public static final String DEFAULT_HOST = "localhost" ;
+
+    /** tcp port value set by reading config.xml */
+    private int m_port ;
+    /** server socket backlog value set by reading config.xml */
+    private int m_backlog ;
+    /** inet address to listen on set by reading config.xml */
+    private InetAddress m_address ;
+    /** ldap url composed by using port and host values */
+	private String m_ldapUrl = null ;
+    /** handle on the client manager service */
+    private ClientManager m_clientManager = null ;
+    /** server socket used to listen for incomming connections */
+	private ServerSocket m_serverSocket = null ;
+
+
+	////////////////////////
+    // Some MBean Methods //
+	////////////////////////
+
+
+    /**
+     * Gets the tcp port this listener listens to for client connections.
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the tcp port listened to.
+     * @phoenix:mx-isWriteable no
+     */
+    public int getPort()
+    {
+        return m_port ;
+    }
+
+
+    /**
+     * Gets the ip interface listened to for client connections as an address
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the ip address listened to.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getAddress()
+    {
+        return m_address.getHostAddress() ;
+    }
+
+
+    /**
+     * Gets the effect ldap url of this listener using the port and address
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the ldapd URL of this listener
+     * @phoenix:mx-isWriteable no
+     */
+    public String getLdapURL()
+    {
+        return m_ldapUrl ;
+    }
+
+
+    /**
+     * Gets the maximum possible number of client connections backlogged on this
+     * listener's server socket before rejecting client connections.
+     * 
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the server socket backlog
+     * @phoenix:mx-isWriteable no
+     */
+    public int getBacklog()
+    {
+        return m_backlog ;
+    }
+
+
+    ////////////////////////
+    // Life-Cycle Methods //
+    ////////////////////////
+
+
+    /**
+     * Runnable implementation which runs in a loop until this module is
+     * stopped.  The loop waits blocked for client connections to come in via
+     * the accept socket call on the server socket.  Once a connection comes in
+     * a ConnectEvent is created containing the client socket returned from the
+     * accept call.  The event is then enqueued onto the event queue of the
+     * client manager stage using the connectPerformed method on the
+     * ClientManager.  Once the event is enqueued the loop sits waiting for the
+     * next client connection.
+     */
+	public void run()
+    {
+		if(getLogger().isDebugEnabled()) {
+			getLogger().debug("Listening for LDAP clients at " + m_ldapUrl) ;
+		}
+
+
+        while(hasStarted()) {
+            try {
+				Socket l_clientSocket = m_serverSocket.accept() ;
+
+				if(getLogger().isDebugEnabled()) {
+                    getLogger().debug("Client connected from " +
+                        l_clientSocket.getInetAddress()) ;
+                }
+
+                ConnectEvent l_event = new ConnectEvent(l_clientSocket) ;
+                m_clientManager.connectPerformed(l_event) ;
+            } catch(IOException e) {
+                getLogger().error("IO failure on accept(): ", e) ;
+                throw new ListenerException("IO failure on accept(): ", e) ;
+            }
+        }
+    }
+
+
+    /**
+     * Module lifecycle method that calls <code> super.start() </code> first
+     * then creates a new thread using this Runnable Module.  The thread is
+     * then started.
+     *
+     * @throws Exception if superclass <code>start()</code> call fails or this
+     * Module's thread <code>start()</code> call fails.
+     */
+    public void start()
+        throws Exception
+    {
+        super.start() ;
+        new Thread(this).start() ;
+    }
+
+
+    /**
+     * Initializes this module by creating and binding the server socket.
+     *
+     * @throws Exception if the bind fails for any reason.
+     */
+    public void initialize()
+        throws Exception
+    {
+        try {
+        	m_serverSocket = new ServerSocket(m_port, m_backlog, m_address) ;
+        } catch(IOException e) {
+            getLogger().error("Error on bind: " + e) ;
+            throw e ;
+        }
+    }
+
+
+    /*
+	<pre>
+    E X A M P L E   C O N F I G U R A T I O N
+	&lt;listener&gt;
+		&lt;port&gt;389&lt;/port&gt;
+        &lt;host&gt;localhost&lt;/host&gt;
+        &lt;backlog&gt;50&lt;/backlog&gt;
+	&lt;/listener&gt;
+    </pre>
+    */
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+        String l_host = a_config.getChild(HOST_TAG).getValue(DEFAULT_HOST) ;
+        m_port = a_config.getChild(PORT_TAG).getValueAsInteger(DEFAULT_PORT) ;
+		m_backlog =
+            a_config.getChild(BACKLOG_TAG).getValueAsInteger(DEFAULT_BACKLOG) ;
+
+        try {
+			m_address = InetAddress.getByName(l_host) ;
+        } catch(UnknownHostException e) {
+			throw new ConfigurationException("Could not resolve host " +
+                l_host, e) ;
+        }
+
+        m_ldapUrl = "ldap://" + l_host + ":" + m_port ;
+        if(getLogger().isDebugEnabled()) {
+			getLogger().debug("Configured to listen on port "+ m_port
+				+ " with host address " + m_address) ;
+        }
+    }
+
+
+	/**
+     * Extracts a handle on the system ClientManager from the ServiceManager.
+     * 
+     * @phoenix:dependency name="org.apache.eve.client.ClientManager"
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        m_clientManager = (ClientManager) a_manager.lookup(ClientManager.ROLE) ;
+    }
+
+
+    /**
+     * Gets this Module implementation's service interface (a.k.a its role)
+     *
+     * @return the service interface name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the service interface (ROLE)
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets this Module implementation's descriptive name.
+     *
+     * @return descriptive module name
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the descriptive name
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "Server Socket Listener Module" ;
+    }
+
+
+    /**
+     * Gets this Module implementation's fully qualified class name.
+     *
+     * @return the fqcn
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description gets the FQCN
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ServerListener.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/listener/ServerListener.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,58 @@
+/*
+ * $Id: ServerListener.java,v 1.4 2003/03/13 18:27:39 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.listener ;
+
+
+
+import org.apache.eve.event.ConnectListener ;
+
+
+/**
+ * The ServiceListener service interface is implemented by server socket
+ * listner modules in the LDAPd server.  It currently is designed to only
+ * support one server socket.  Expect this interface to change in the near
+ * future to accomodate multiple socket listeners and SSL enabled server
+ * sockets.
+ */
+public interface ServerListener
+{
+    /** role of this service interface */
+    public static final String ROLE = ServerListener.class.getName() ;
+
+    /**
+     * Gets the server socket backlog for this ServerListener
+     *
+     * @return client connection backlog
+     */
+    public int getBacklog() ;
+
+    /**
+     * Gets the TCP port number this ServerListener listens on.
+     *
+     * @return the tcp port number
+     */
+    public int getPort() ;
+
+    /**
+     * Gets the ip interface address this ServerListener listens on.
+     *
+     * @return the ip address octets as a String i.e. 127.0.0.1
+     */
+    public String getAddress() ;
+
+    /**
+     * Gets the LDAP URL for this ServerListener using the specified ip address
+     * and the tcp port number listened to.  The ipaddress is resolved to a host
+     * name.
+     *
+     * @return the LDAP URL like so ldap://localhost:389
+     */
+    public String getLdapURL() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,34 @@
+/*
+ * $Id: OutputManager.java,v 1.4 2003/03/13 18:27:41 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.output ;
+
+
+import java.io.OutputStream ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.event.OutputListener;
+import org.apache.eve.client.ClientManagerSlave;
+import java.io.InputStream;
+import java.io.IOException;
+
+
+public interface OutputManager
+    extends OutputListener, ClientManagerSlave
+{
+    public static final String ROLE = OutputManager.class.getName() ;
+
+    /**
+     * Synchronous write which reads from the InputStream argument writing
+     * it to the client's OutputStream.
+     */
+    public void write(ClientKey a_clientKey, InputStream an_in)
+        throws IOException ;
+    void register(ClientKey a_clientKey, OutputStream l_clientOut) ;
+    void unregister(ClientKey a_clientKey) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/output/OutputModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,208 @@
+/*
+ * $Id: OutputModule.java,v 1.10 2003/04/21 19:13:51 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.output ;
+
+
+import org.apache.eve.seda.AbstractStage ;
+import org.apache.eve.client.ClientKey;
+import java.io.OutputStream;
+import org.apache.eve.event.OutputEvent;
+import java.util.HashMap;
+import java.util.Map;
+import java.io.InputStream;
+import java.io.IOException;
+import org.apache.eve.event.AbstractEventHandler;
+import org.apache.eve.client.ClientManager;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.logger.Logger;
+import java.util.EventObject;
+import org.apache.eve.client.KeyExpiryException;
+import java.io.BufferedOutputStream;
+
+/**
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.output.OutputManager"
+ */
+public class OutputModule
+    extends AbstractStage
+    implements OutputManager
+{
+    private Map m_streams = new HashMap() ;
+    private ClientManager m_clientManager = null ;
+
+
+    public OutputModule()
+    {
+        m_handler = new OutputEventHandler() ;
+    }
+
+
+    class OutputEventHandler extends AbstractEventHandler
+    {
+		public void handleEvent(EventObject an_event)
+		{
+			if(an_event instanceof OutputEvent) {
+				OutputEvent l_event = (OutputEvent) an_event ;
+				ClientKey l_clientKey = l_event.getClientKey() ;
+
+				try {
+					write(l_clientKey, l_event.getInputStream()) ;
+				} catch(IOException e) {
+					getLogger().error("Abruptly dropping client "
+						+ l_clientKey + ": ", e) ;
+					m_clientManager.drop(l_clientKey) ;
+				}
+			}
+		}
+    }
+
+
+    public void register( ClientKey a_clientKey, OutputStream l_clientOut )
+    {
+        synchronized( m_streams )
+        {
+	        m_streams.put( a_clientKey, l_clientOut ) ;
+        }
+    }
+
+
+    public void unregister( ClientKey a_clientKey )
+    {
+        synchronized( m_streams )
+        {
+	        m_streams.remove( a_clientKey ) ;
+        }
+    }
+
+
+    public void registerClientManager(ClientManager a_manager)
+    {
+        m_clientManager = a_manager ;
+    }
+
+
+    public void writeResponse(OutputEvent an_event)
+    {
+        enqueue(an_event) ;
+    }
+
+
+    public void write(ClientKey a_clientKey, InputStream an_in)
+        throws IOException
+    {
+        Object l_lock = null ;
+        OutputStream l_out = null ;
+
+        synchronized( m_streams )
+        {
+            l_out = new BufferedOutputStream((OutputStream)
+                m_streams.get(a_clientKey)) ;
+        }
+
+        if(null == l_out) {
+            getLogger().error("Write to client " + a_clientKey +
+                " aborted: client output stream not registered!") ;
+            return ;
+        }
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("Output stream lookup succeeded for client: "
+                + a_clientKey) ;
+            getLogger().debug("About to lock on client " + a_clientKey
+                + " outputLock") ;
+        }
+
+        // Obtain output lock for write to client.
+        try {
+            l_lock = a_clientKey.getOutputLock() ;
+        } catch(KeyExpiryException e) {
+			// Log inability to deliver response to disconnected client and exit
+			if(getLogger().isInfoEnabled()) {
+				getLogger().info("Client " + a_clientKey
+                    + " disconnected or was dropped before response delivery") ;
+			}
+            return ;
+        }
+
+        // Synchronize on client output stream lock object.
+		synchronized(l_lock) {
+			if(getLogger().isDebugEnabled()) {
+				getLogger().debug("Successfully locked on socket "
+					+ "output stream - writing to client: " + a_clientKey) ;
+			}
+
+            //
+            // Cycle writes to output stream while the client is connected and
+            // the response content input stream still has data to read from.
+            // Use 512 byte buffer since buffered output stream by default uses
+            // a 512 byte buffer.
+            //
+
+            byte [] l_buf = new byte[512] ;
+            int l_length = -1 ;
+			while(!a_clientKey.hasExpired() &&
+                ((l_length = an_in.read(l_buf)) != -1))
+            {
+				l_out.write(l_buf, 0, l_length) ;
+            }
+
+			l_out.flush() ;
+			l_lock.notifyAll() ;
+		}
+
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("Write to client " + a_clientKey +
+                " socket output stream complete - PDU delivered!") ;
+        }
+    }
+
+
+    /////////////////////////////////
+    // Module & Life-Cycle Methods //
+    /////////////////////////////////
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        super.enableLogging(a_logger) ;
+        m_handler.enableLogging(a_logger) ;
+    }
+
+
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    public String getImplementationName()
+    {
+        return "Client Output Manager Module" ;
+    }
+
+
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    /**
+     * Needed for the javadoclet!
+     * 
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        super.service(a_manager) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AbandonHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AbandonHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,97 @@
+/*
+ * $Id: AbandonHandler.java,v 1.2 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import java.math.BigInteger ;
+
+import org.apache.ldap.common.message.Request ;
+import org.apache.ldap.common.message.AbandonRequest ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.NotImplementedException ;
+
+
+/**
+ * Handles the processing of AbandonRequests.  Not presently implemented.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public final class AbandonHandler
+    implements NoReplyHandler
+{
+    /** Reference to the protocol module this handler is part of */
+	private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a handler for AbandonRequests to work on behalf of a
+     * ProtocolModule.
+     *
+     * @param a_module the ProtocolModule this handler is part of.
+     */
+	public AbandonHandler( ProtocolModule a_module )
+    {
+		m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type enumeration constant associated with this handler.
+     *
+     * @return HandlerTypeEnum.NOREPLY
+     */
+	public final HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.NOREPLY ;
+    }
+
+
+    /**
+     * Gets the message type enumeration constant associated with this handler.
+     *
+     * @return HandlerTypeEnum.NOREPLY
+     */
+	public final MessageTypeEnum getRequestType()
+    {
+        return MessageTypeEnum.ABANDONREQUEST ;
+    }
+
+
+    /**
+     * Handles an AbandonRequest by stopping the outstanding request specified.
+     *
+     * @param a_request the AbandonRequest to handle.
+     * @throws ClassCastException if the a_request argument is not an
+     * AbandonRequest.
+     */
+    public final void handle( Request a_request )
+    {
+        try
+        {
+			throw new NotImplementedException( "Handler not complete!" ) ;
+        }
+        catch( Throwable t )
+        {
+            m_module.getLogger().error( "Failed on AbandonRequest!", t ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AddHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/AddHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,137 @@
+/*
+ * $Id: AddHandler.java,v 1.2 2003/08/22 21:15:55 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.ldap.LdapContext ;
+import javax.naming.directory.Attributes ;
+
+import org.apache.ldap.common.message.AddRequest ;
+import org.apache.ldap.common.message.AddResponse ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.AddResponseImpl ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+
+
+/**
+ * AddRequest handler for add protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class AddHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a AddRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public AddHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.ADDREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.ADDRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a AddRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        Name l_dn = null ;
+        AddRequest l_request = ( AddRequest ) a_request ;
+		AddResponse l_response =
+            new AddResponseImpl( a_request.getMessageId() ) ;
+        Attributes l_attributes = l_request.getEntry() ;
+
+        try
+        {
+            l_dn = m_module.getName( l_request.getName() ) ;
+
+            // Get the context to the parent and create new subcontext for
+            // the entry we are currently adding.
+			LdapContext l_parent = ( LdapContext )
+                m_module.getContext( l_dn.getPrefix( l_dn.size() - 1 ) ) ;
+			l_parent.createSubcontext( l_dn.get( l_dn.size()-1 ),
+                    l_attributes ) ;
+
+            // Set response result to success
+			m_module.setResult( l_response, l_dn ) ;
+        }
+        catch( Throwable t )
+        {
+            // Set response result to error code based on the error.
+            m_module.setResult( l_response, l_dn, t ) ;
+        }
+
+        return l_response ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/BindHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/BindHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,201 @@
+/*
+ * $Id: BindHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.InvalidNameException ;
+import javax.naming.NameNotFoundException ;
+
+import org.apache.ldap.common.message.BindRequest ;
+import org.apache.ldap.common.message.BindResponse ;
+import org.apache.ldap.common.message.ResultCodeEnum ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.BindResponseImpl ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.client.ClientManager ;
+import org.apache.eve.security.LdapPrincipal ;
+import org.apache.eve.backend.BackendException ;
+import org.apache.eve.security.auth.AuthenticationManager ;
+import org.apache.eve.security.auth.AuthenticationException ;
+
+
+/**
+ * BindRequest handler for bind protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class BindHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a BindRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public BindHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.BINDREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.BINDRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a BindRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        Name l_dn = null ;
+		BindRequest l_request = ( BindRequest ) a_request ;
+
+        // Prepare the response wrapper ahead of time.
+        BindResponse l_response =
+            new BindResponseImpl( l_request.getMessageId() ) ;
+
+		try
+		{
+			l_dn = m_module.getName( l_request.getName() ) ;
+		}
+		// Respond to the user with an INVALIDDNSYNTAX error response
+		catch( NamingException ne )
+		{
+			String l_msg = "'" + l_request.getName() + "' for the bind"
+				+ " user's DN does not conform to the DN syntax." ;
+			m_module.setResult( l_response, ResultCodeEnum.INVALIDDNSYNTAX,
+				l_msg, ne ) ;
+			return l_response ;
+		}
+
+		// Check if unsupported SASL mechanisms are being used.  Use of
+        // SASL mechanisms result in a AUTHMETHODNOTSUPPORTED error.
+		if( ! l_request.isSimple() )
+        {
+            m_module.setResult( l_response,
+                ResultCodeEnum.AUTHMETHODNOTSUPPORTED, l_dn,
+                "SASL based authentication methods not supported!", null ) ;
+    		return l_response ;
+        }
+
+		// Perform simple authentication using the authentication manager
+		try
+        {
+            AuthenticationManager l_am = m_module.getAuthenticationManager() ;
+            LdapPrincipal l_principal = l_am.loginSimple( l_dn,
+                new String( l_request.getCredentials() ) ) ;
+            ClientManager l_cm = m_module.getClientManager() ;
+            ClientKey l_clientKey = l_cm.getClientSession().getClientKey() ;
+            l_cm.setUserPrincipal( l_clientKey, l_principal ) ;
+            m_module.setResult( l_response, l_dn ) ;
+        }
+        catch( InvalidNameException ine )
+        {
+            String l_msg = "InvalidNameException should never be thrown by the "
+                + "AuthenticationManager since we have already verified a "
+                + "correct Dn syntax." ;
+            m_module.setResult( l_response, ResultCodeEnum.INVALIDDNSYNTAX,
+                l_dn, l_msg, ine ) ;
+        }
+        catch( NameNotFoundException nnfe )
+        {
+            String l_msg = "NameNotFoundException should never be thrown by the"
+                + " AuthenticationManager since we have already verified the "
+                + "exsitiance of the entry '" + l_request.getName() + "'" ;
+            m_module.setResult( l_response, ResultCodeEnum.NOSUCHOBJECT, l_dn,
+                l_msg, nnfe ) ;
+        }
+        catch( NamingException ne )
+        {
+            m_module.setResult( l_response, l_dn, ne ) ;
+        }
+        catch( BackendException be )
+        {
+            m_module.setResult( l_response, l_dn, be ) ;
+        }
+        catch( AuthenticationException ae )
+        {
+            String l_msg = "'" + l_request.getName() + "' is either not the "
+                + "correct username associated with the supplied password." ;
+            m_module.setResult( l_response, ResultCodeEnum.INVALIDCREDENTIALS,
+                l_dn, l_msg, ae ) ;
+        }
+        catch( IllegalArgumentException iae )
+        {
+            String l_msg = "No backend for the namespace associated with '"
+                + l_request.getName() + "' exists.  Check your backend "
+                + "configuration to determine the suffix to use." ;
+            m_module.setResult( l_response, ResultCodeEnum.NOSUCHOBJECT,
+                l_dn, l_msg, iae ) ;
+        }
+
+        return l_response ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/CompareHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/CompareHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,106 @@
+/*
+ * $Id: CompareHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.CompareRequest ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.NotImplementedException ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+
+/**
+ * CompareRequest handler for compare protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class CompareHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a CompareRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public CompareHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.COMPAREREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.COMPARERESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a CompareRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        CompareRequest l_request = ( CompareRequest ) a_request ;
+        throw new NotImplementedException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/DeleteHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/DeleteHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,125 @@
+/*
+ * $Id: DeleteHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.DeleteRequest ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+import org.apache.ldap.common.message.DeleteResponse;
+import org.apache.ldap.common.message.DeleteResponseImpl;
+import javax.naming.NamingException;
+import javax.naming.InitialContext;
+
+
+/**
+ * DeleteRequest handler for delete protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class DeleteHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a DeleteRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public DeleteHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.DELREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.DELRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a DeleteRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        InitialContext l_initCtx ;
+        DeleteRequest l_request = ( DeleteRequest ) a_request ;
+        DeleteResponse l_response =
+            new DeleteResponseImpl( l_request.getMessageId() ) ;
+
+		try
+		{
+            l_initCtx = Utils.getInitialContext() ;
+            l_initCtx.destroySubcontext( l_request.getName() ) ;
+            Utils.setResult( l_response, l_request.getName(), false ) ;
+        }
+        // Could be anything here.
+        catch( NamingException ne )
+        {
+			Utils.setResult( l_response, l_request.getName(), ne ) ;
+        }
+
+		return l_response ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ExtendedHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ExtendedHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,106 @@
+/*
+ * $Id: ExtendedHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.AddRequest ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.NotImplementedException ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+
+/**
+ * ExtendedRequest handler for extended protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class ExtendedHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a ExtendedRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public ExtendedHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.EXTENDEDREQ ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.ADDRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a AddRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        AddRequest l_request = ( AddRequest ) a_request ;
+        throw new NotImplementedException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/HandlerTypeEnum.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/HandlerTypeEnum.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,55 @@
+/*
+ * $Id: HandlerTypeEnum.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.avalon.framework.ValuedEnum ;
+
+
+/**
+ * Valued enumeration for the three types of handlers: NOREPLY, SINGLEREPLY,
+ * and SEARCH.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class HandlerTypeEnum
+    extends ValuedEnum
+{
+    /** Value for noreply enumeration type */
+    public static final int NOREPLY_VAL = 0 ;
+    /** Value for singlereply enumeration type */
+    public static final int SINGLEREPLY_VAL = 1 ;
+    /** Value for search enumeration type */
+    public static final int SEARCH_VAL = 2 ;
+
+    /** Enum for noreply type */
+	public static final HandlerTypeEnum NOREPLY =
+        new HandlerTypeEnum("NOREPLY", NOREPLY_VAL) ;
+    /** Enum for singlereply type */
+	public static final HandlerTypeEnum SINGLEREPLY =
+        new HandlerTypeEnum("SINGLEREPLY", SINGLEREPLY_VAL) ;
+    /** Enum for search type */
+	public static final HandlerTypeEnum SEARCH =
+        new HandlerTypeEnum("SEARCH", SEARCH_VAL) ;
+
+
+    /**
+     * Enables creation of constants in this class only.
+     *
+     * @param a_name the name of the enum
+     * @param a_value the value of the enum
+     */
+	private HandlerTypeEnum( String a_name, int a_value )
+    {
+        super( a_name, a_value ) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDNRequestProcessor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDNRequestProcessor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,258 @@
+/*
+ * $Id: ModifyDNRequestProcessor.java,v 1.10 2003/08/22 21:15:56 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import javax.naming.Name ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.event.protocol.EventManager;
+import org.apache.eve.event.protocol.ModifyDnEvent;
+
+
+/**
+ * Processes an LDAP request to modify an entry's DN either changing its name or
+ * relocation the DIT branch at an entry under a new parent entry.  The protocol
+ * in <a href="http://www.faqs.org/rfcs/rfc2251.html">RFC 2251<a> defines the
+ * request processed by the RequestProcessor.
+ * <pre>
+ *     The Modify DN Operation allows a client to change the leftmost (least
+ * significant) component of the name of an entry in the directory, or
+ * to move a subtree of entries to a new location in the directory.  The
+ * Modify DN Request is defined as follows:
+ *
+ *      ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+ *              entry           LDAPDN,
+ *              newrdn          RelativeLDAPDN,
+ *              deleteoldrdn    BOOLEAN,
+ *              newSuperior     [0] LDAPDN OPTIONAL }
+ *
+ * </pre>
+ */
+public class ModifyDNRequestProcessor
+//    extends BaseRequestProcessor
+{
+    /** Response type of this request processor class *
+    public static final int RES_TYPE = LDAPMessageChoice.MODDNRESPONSE_CID ;
+
+
+    private EventManager m_eventManager = null ;
+    private LDAPMessage m_response = null ;
+	private UnifiedBackend m_nexus = null ;
+
+
+    /**
+     * Creates and initializes the request processor.
+     *
+    public ModifyDNRequestProcessor(ClientKey a_client, LDAPMessage a_request)
+    {
+        super(a_client, a_request, RES_TYPE) ;
+    }
+
+
+    /**
+     * Processes the LDAP ModifyDN request.  The parameters of the request are
+     * transduced into arguments fed into the move or modifyRdn methods of the
+     * Backend nexus.  Below you'll find a description of the parameters
+     * packaged in the ModifyRdn PDU:<br>
+     * <pre>
+     * Parameters of the Modify DN Request are:
+     *
+     * - entry: the Distinguished Name of the entry to be changed.  This
+     *   entry may or may not have subordinate entries.
+     *
+     * - newrdn: the RDN that will form the leftmost component of the new
+     *   name of the entry.
+     *
+     * - deleteoldrdn: a boolean parameter that controls whether the old RDN
+     *   attribute values are to be retained as attributes of the entry, or
+     *   deleted from the entry.
+     *
+     * - newSuperior: if present, this is the Distinguished Name of the entry
+     *   which becomes the immediate superior of the existing entry.
+     * </pre>
+     *
+     * @return the response message envelope formulated according to the
+     * results of the ModifyDN request.
+     *
+    public LDAPMessage process()
+    {
+        try 
+        {
+            ModifyDnEvent l_event = null ;
+            String l_supDnStr = getSuperiorEntryDN() ;
+            Name l_dn = m_nexus.getNormalizedName( getEntryDN() ) ;
+            Name l_rdn = m_nexus.getNormalizedName( getNewRdn() ) ;
+            Name l_superior = m_nexus.getNormalizedName( l_supDnStr ) ;
+            LdapEntry l_entry = m_nexus.read( l_dn ) ;
+
+            if ( getLogger().isDebugEnabled() ) 
+            {
+                getLogger().debug( "ModifyDNRequestProcessor: delete oldrdn = "
+                    + deleteOldRdn() ) ;
+                getLogger().debug( "ModifyDNRequestProcessor: dn = " 
+                    + l_dn ) ;
+                getLogger().debug( "ModifyDNRequestProcessor: rdn = " 
+                    + l_rdn ) ;
+                getLogger().debug( "ModifyDNRequestProcessor: superior = "
+                    + l_superior ) ;
+            }
+
+            
+            if ( l_rdn.size() > 1 )
+            {
+                setResponse( LDAPResultEnum.INVALIDDNSYNTAX, null,
+                    "ModifyDn: Expecting either a null RDN or one of length 1 " 
+                    + "but got RDN of length " + l_rdn.size() + " for '" 
+                    + l_rdn + "'" ) ;
+            }
+            
+
+            /*
+             * If the superior Dn String argument in the PDU is null then we
+             * have a simple rdn name change as opposed to a move operation
+             *
+            if ( l_supDnStr == null)
+            {
+                m_nexus.modifyRdn( l_entry, l_rdn, deleteOldRdn() ) ;
+            } 
+            else if ( l_rdn.size() == 0 ) 
+            {
+                LdapEntry l_parent = m_nexus.read( l_superior ) ;
+                m_nexus.move( l_parent, l_entry ) ;
+            } 
+            else 
+            {
+                LdapEntry l_parent = m_nexus.read( l_superior ) ;
+                m_nexus.move( l_parent, l_entry, l_rdn, deleteOldRdn() ) ;
+            }
+
+            setResponse( LDAPResultEnum.SUCCESS, getEntryDNBytes(),
+                "DN Modifications Successfully Completed!" ) ;
+
+        } 
+        catch ( Throwable t ) 
+        {
+            if( getLogger().isDebugEnabled() ) 
+            {
+                setResponse( LDAPResultEnum.OPERATIONSERROR, null, t ) ;
+            } 
+            else 
+            {
+                setResponse( LDAPResultEnum.OPERATIONSERROR, null,
+                    t.getMessage() ) ;
+            }
+        }
+
+        return m_response ;
+    }
+
+
+    public boolean deleteOldRdn()
+    {
+        return m_request.protocolOp.modDNRequest.deleteoldrdn ;
+    }
+
+
+    public String getSuperiorEntryDN()
+    {
+        if(m_request.protocolOp.modDNRequest.newSuperior != null) {
+            return new String(m_request.protocolOp.modDNRequest.newSuperior) ;
+        } else {
+            return null ;
+        }
+    }
+
+
+    public String getNewRdn()
+    {
+        if(m_request.protocolOp.modDNRequest.newrdn != null) {
+            return new String(m_request.protocolOp.modDNRequest.newrdn) ;
+        } else {
+            return null ;
+        }
+    }
+
+
+    public String getEntryDN()
+    {
+        return new String(m_request.protocolOp.modDNRequest.entry) ;
+    }
+
+
+    public byte [] getEntryDNBytes()
+    {
+        return m_request.protocolOp.modDNRequest.entry ;
+    }
+
+
+    public void setResponse(int a_resultType, byte [] a_dn,
+        Throwable a_throwable)
+    {
+        setResponse(a_resultType, a_dn,
+            ExceptionUtil.printStackTrace(a_throwable)) ;
+    }
+
+
+    public void setResponse(int a_resultType, byte [] a_dn, String an_errMsg)
+    {
+        m_response.protocolOp.modDNResponse.resultCode.value = a_resultType ;
+
+        if(an_errMsg != null) {
+            m_response.protocolOp.modDNResponse.errorMessage =
+                an_errMsg.getBytes() ;
+        } else {
+            m_response.protocolOp.modDNResponse.errorMessage =
+                "".getBytes() ;
+        }
+
+        if(a_dn == null) {
+            m_response.protocolOp.modDNResponse.matchedDN = "".getBytes() ;
+        } else {
+            m_response.protocolOp.modDNResponse.matchedDN = a_dn ;
+        }
+    }
+
+
+    ////////////////////////
+    // Life-Cycle Methods //
+    ////////////////////////
+
+
+    public void initialize()
+        throws Exception
+    {
+        m_response = new LDAPMessage() ;
+        m_response.messageID = m_request.messageID ;
+        LDAPMessageChoice l_protocolOp = new LDAPMessageChoice() ;
+        l_protocolOp.choiceId = this.m_responseChoiceId ;
+        ModifyDNResponse l_modDNResponse = new ModifyDNResponse() ;
+        LDAPResultEnum l_resultCode = new LDAPResultEnum() ;
+        l_modDNResponse.resultCode =  l_resultCode ;
+		l_protocolOp.modDNResponse = l_modDNResponse ;
+		m_response.protocolOp = l_protocolOp ;
+    }
+
+
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        m_nexus = (UnifiedBackend) a_manager.lookup(UnifiedBackend.ROLE) ;
+        m_eventManager = (EventManager) a_manager.lookup(EventManager.ROLE) ;
+    }
+    */
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDnHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyDnHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,106 @@
+/*
+ * $Id: ModifyDnHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.NotImplementedException ;
+import org.apache.ldap.common.message.ModifyDnRequest ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+
+/**
+ * ModifyDnRequest handler for ModifyDn protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class ModifyDnHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a ModifyDnRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public ModifyDnHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.MODDNREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.MODDNRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a ModifyRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+        ModifyDnRequest l_request = ( ModifyDnRequest ) a_request ;
+        throw new NotImplementedException() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ModifyHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,173 @@
+/*
+ * $Id: ModifyHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.ModifyRequest ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+import javax.naming.Name;
+import org.apache.eve.backend.UnifiedBackend;
+import org.apache.ldap.common.message.ModifyResponseImpl;
+import org.apache.ldap.common.message.ModifyResponse;
+import java.util.Iterator;
+import javax.naming.directory.ModificationItem;
+import org.apache.eve.backend.LdapEntry;
+import org.apache.ldap.common.message.ResultCodeEnum;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.Attribute;
+
+
+/**
+ * ModifyRequest handler for modify protocol requests.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class ModifyHandler
+	implements SingleReplyHandler
+{
+    /** The protocol module this request handler is part of */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a ModifyRequest protocol data unit handler.
+     *
+     * @param a_module the module this handler is associated with.
+     */
+    public ModifyHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SINGLEREPLY ;
+    }
+
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+		return MessageTypeEnum.MODIFYREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    public MessageTypeEnum getResponseType()
+    {
+        return MessageTypeEnum.MODIFYRESPONSE ;
+    }
+
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     * @throws ClassCastException if a_request is not a ModifyRequest
+     */
+    public ResultResponse handle( SingleReplyRequest a_request )
+    {
+    	Name l_dn = null ;
+        LdapEntry l_entry ;
+        UnifiedBackend l_nexus = m_module.getNexus() ;
+		ModifyRequest l_request = ( ModifyRequest ) a_request ;
+        ModifyResponse l_response =
+            new ModifyResponseImpl( a_request.getMessageId() ) ;
+
+        try
+        {
+            l_dn = m_module.getName( l_request.getName() ) ;
+
+            if( ! l_nexus.hasEntry( l_dn ) )
+            {
+				m_module.setResult( l_response, ResultCodeEnum.NOSUCHOBJECT,
+                    l_dn, "Entry does not exist - modification not possible" ) ;
+                return l_response ;
+            }
+
+			l_entry = l_nexus.read( l_dn ) ;
+
+            Iterator l_list = l_request.getModificationItems().iterator() ;
+            while( l_list.hasNext() )
+            {
+				ModificationItem l_item = ( ModificationItem ) l_list.next() ;
+                Attribute l_attr = l_item.getAttribute() ;
+
+				switch( l_item.getModificationOp() )
+                {
+                case( DirContext.ADD_ATTRIBUTE ):
+                    for( int ii = 0; ii > l_attr.size(); ii++ )
+                	{
+                    	l_entry.addValue( l_attr.getID(), l_attr.get( ii ) ) ;
+                	}
+                    break ;
+                case( DirContext.REMOVE_ATTRIBUTE ):
+                    for( int ii = 0; ii > l_attr.size(); ii++ )
+                	{
+                    	l_entry.removeValue( l_attr.getID(),
+                            l_attr.get( ii ) ) ;
+                	}
+                    break ;
+                case( DirContext.REPLACE_ATTRIBUTE ):
+                    l_entry.removeValues( l_attr.getID() ) ;
+                    for( int ii = 0; ii < l_attr.size(); ii++ )
+                	{
+                    	l_entry.addValue( l_attr.getID(), l_attr.get( ii ) ) ;
+                	}
+                    break ;
+                }
+            }
+
+            l_nexus.update( l_entry ) ;
+            m_module.setResult( l_response, l_dn ) ;
+        }
+        catch( Throwable t )
+        {
+            m_module.setResult( l_response, l_dn, t ) ;
+        }
+
+        return l_response ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/NoReplyHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/NoReplyHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,33 @@
+/*
+ * $Id: NoReplyHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.Request ;
+
+
+/**
+ * Represents handlers that do not return a response to the sender.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface NoReplyHandler
+    extends RequestHandler
+{
+    /**
+     * Handles requests that do not reply to the requesting client with a
+     * response.
+     *
+     * @param a_request the request without a response.
+     */
+    void handle( Request a_request ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolEngine.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolEngine.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,36 @@
+/*
+ * $Id: ProtocolEngine.java,v 1.5 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.eve.event.RequestListener ;
+import org.apache.eve.client.ClientManagerSlave ;
+
+
+/**
+ * Service interface for an LDAP protocol engine.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.5 $
+ */
+public interface ProtocolEngine
+    extends RequestListener, ClientManagerSlave
+{
+    /** The fully qualified name of this service interface */
+    String ROLE = ProtocolEngine.class.getName() ;
+
+    /**
+     * Gets the highest LDAP protocol version supported by an implementation.
+     * 
+     * @return the highest supported protocol version.
+     */
+    int getProtocolVersion() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: ProtocolException.java,v 1.3 2003/03/13 18:27:54 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+/** This exception is thrown when protocol errors occurred */
+public class ProtocolException extends CascadingRuntimeException
+{
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ProtocolException(String message, Throwable t)
+    {
+        super(message, t) ;
+    }
+
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public ProtocolException(String message)
+    {
+        super(message, null) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/ProtocolModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,786 @@
+/*
+ * $Id: ProtocolModule.java,v 1.11 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.EventObject ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+
+import org.apache.avalon.framework.logger.Logger ;
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.ldap.common.message.Request ;
+import org.apache.ldap.common.message.LdapResult ;
+import org.apache.ldap.common.message.SearchRequest ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.LdapResultImpl ;
+import org.apache.ldap.common.message.ResultCodeEnum ;
+import org.apache.ldap.common.message.AddResponseImpl ;
+import org.apache.ldap.common.message.BindResponseImpl ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.ModifyResponseImpl ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+import org.apache.ldap.common.message.DeleteResponseImpl ;
+import org.apache.ldap.common.message.CompareResponseImpl ;
+import org.apache.ldap.common.message.ExtendedResponseImpl ;
+import org.apache.ldap.common.message.ModifyDnResponseImpl ;
+
+import org.apache.eve.encoder.Encoder ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.seda.AbstractStage ;
+import org.apache.eve.event.RequestEvent ;
+import org.apache.eve.event.ResponseEvent ;
+import org.apache.eve.client.ClientManager ;
+import org.apache.eve.output.OutputManager ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.event.AbstractEventHandler ;
+import org.apache.eve.event.protocol.EventManager ;
+import org.apache.eve.protocol.extended.PayloadHandler ;
+import org.apache.eve.security.auth.AuthenticationManager ;
+
+import javax.naming.ldap.LdapContext ;
+import java.util.Hashtable ;
+import javax.naming.Context ;
+import javax.naming.InitialContext ;
+
+
+/**
+ * Protocol engine stage: the request processing stage of the pipeline.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.protocol.ProtocolEngine"
+ * @phoenix:mx-topic name="ProtocolModule"
+ */
+public class ProtocolModule
+    extends AbstractStage
+    implements ProtocolEngine
+{
+	/** The version support by this ProtocolEngine */
+    public static final int PROTOCOL_VERSION = 3 ;
+    /** Extended request handler configuration tag name */
+    public static final String HANDLER_TAG = "handler" ;
+    /** Extended request handler configuration 'oid' attribute name */
+    public static final String OID_ATTR = "oid" ;
+    /** Extended request handler configuration handler 'class' attribute name */
+    public static final String CLASS_ATTR = "class" ;
+
+    /** Lookup Table of MessageTypeEnums to the Request's respective handler */
+    private Map m_handlers = new HashMap( 10 ) ;
+    /** Map of extended request OIDs to the respective request handlers */
+    private Map m_extendedHandlers = new HashMap() ;
+
+
+    // ------------------------------------------------------------------------
+    // Blocks the ProtocolModule depends on
+    // ------------------------------------------------------------------------
+
+    /** Reference to the event manager to dispatch protocol events */
+    private EventManager m_eventManager = null ;
+    /** Reference to the client manager to manage client sessions */
+    private ClientManager m_clientManager = null ;
+	/** Reference to the nexus which several request handlers depend on */
+	private UnifiedBackend m_nexus = null ;
+    /** Reference to the authentication manager for bind operations */
+	private AuthenticationManager m_authManager = null ;
+    /** Reference to the encoder to hande off response events to */
+	private Encoder m_encoder = null ;
+    /** Reference to the output manager synchronously search responses */
+    private OutputManager m_outputManager = null ;
+
+    // ------------------------------------------------------------------------
+    // Explicit Default Constructor
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Instantiates this module and creates the stage event handler so it can
+     * be log enabled in the first lifecycle method.
+     *
+     * @todo look into the correct way to enable logging in these handlers while
+     * making their instantiation reside within the initialize life-cycle
+     * method.
+     */
+    public ProtocolModule()
+    {
+        m_handler = new RequestEventHandler() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestListener Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Recieves a SEDA RequstEvent by simply enqueing it onto the stage queue.
+     *
+     * @param a_event the enqueued RequestEvent
+     */
+    public void requestReceived( RequestEvent a_event )
+    {
+        enqueue(a_event) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // ProtocolEngine Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the protocol version of this ProtocolEngine implementation.
+     *
+     * @return 2 if the protocol implementation is LDAPv2, otherwise 3
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description the LDAP protocol version of this module.
+     * @phoenix:mx-isWriteable no
+     */
+    public int getProtocolVersion()
+    {
+        return PROTOCOL_VERSION ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // ClientManagerSlave Interface Method Implementation
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Registers the client manager this module is to use.
+     *
+     * @param a_manager the ClientManager this module is to become the slave of.
+     */
+    public void registerClientManager(ClientManager a_manager)
+    {
+        m_clientManager = a_manager ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Module Interface Method Implementations.
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the service interface name of this module.
+     *
+     * @return the role of this module's implemented service.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the service role name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    /**
+     * Gets the name of the implementation.  For example the name of the
+     * Berkeley DB Backend module is "Berkeley DB Backend".
+     *
+     * @return String representing the module implementation type name.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationName()
+    {
+        return "LDAP V3 Protocol Module" ;
+    }
+
+
+    /**
+     * Gets the name of the implementation class.  For example the name of the
+     * Berkeley DB Backend implementation class is <code>
+     * "ldapdd.backend.berkeley.BackendBDb" </code>.
+     *
+     * @return String representing the module implementation's class name.
+     * @phoenix:mx-attribute
+     * @phoenix:mx-description Returns the implementation class name.
+     * @phoenix:mx-isWriteable no
+     */
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Avalon Life-Cycle Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Enables logging for this module first through super method call then
+     * log enables this stage's event handler.
+     *
+     * @param a_logger the logger used to log enable this stage.
+     */
+    public void enableLogging( Logger a_logger )
+    {
+        super.enableLogging( a_logger ) ;
+        m_handler.enableLogging( a_logger ) ;
+        Utils.enableLogging( a_logger ) ;
+    }
+
+
+    /**
+     * Need lot of services to get the job done.
+     *
+     * @phoenix:dependency name="org.apache.eve.event.protocol.EventManager"
+     * @phoenix:dependency name="org.apache.eve.backend.UnifiedBackend"
+     * @phoenix:dependency name="org.apache.eve.security.auth.AuthenticationManager"
+     * @phoenix:dependency name="org.apache.eve.output.OutputManager"
+     * @phoenix:dependency name="org.apache.eve.encoder.Encoder"
+     * @phoenix:dependency name="org.apache.avalon.cornerstone.services.threads.ThreadManager"
+     */
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        super.service( a_manager ) ;
+		m_nexus = ( UnifiedBackend ) a_manager.lookup( UnifiedBackend.ROLE ) ;
+        m_authManager = ( AuthenticationManager )
+            a_manager.lookup( AuthenticationManager.ROLE ) ;
+        m_encoder = ( Encoder ) a_manager.lookup( Encoder.ROLE ) ;
+        m_outputManager = ( OutputManager )
+            a_manager.lookup( OutputManager.ROLE ) ;
+        m_eventManager = ( EventManager )
+            a_manager.lookup( EventManager.ROLE ) ;
+    }
+
+
+    /**
+     * Configures the module by loading extended request processor information.
+     *
+     * @param a_config the module's configuration read from config.xml
+     */
+    public void configure( Configuration a_config )
+        throws ConfigurationException
+    {
+        super.configure( a_config ) ;
+
+        PayloadHandler l_handler = null ;
+        Configuration [] l_handlers = a_config.getChildren( HANDLER_TAG ) ;
+        for( int ii = 0 ; ii < l_handlers.length ; ii++ )
+        {
+            String l_oid = l_handlers[ii].getAttribute( OID_ATTR, null ) ;
+            String l_clazz = l_handlers[ii].getAttribute( CLASS_ATTR, null ) ;
+
+            if( null == l_oid )
+            {
+                throw new ConfigurationException(
+                    "Handler must have an 'oid' attribute" ) ;
+            }
+
+            if( null == l_clazz )
+            {
+                throw new ConfigurationException(
+                    "Handler must have a 'class' attribute" ) ;
+            }
+
+            try
+            {
+                l_handler = ( PayloadHandler )
+                    Class.forName( l_clazz ).newInstance() ;
+            }
+            catch( Exception e )
+            {
+                throw new ConfigurationException(
+                    "Failed to instantiate handler class " + l_clazz
+                    + " for extended request OID " + l_oid ) ;
+            }
+
+            m_extendedHandlers.put( l_oid, l_handler ) ;
+        }
+    }
+
+
+    public void initialize()
+        throws Exception
+    {
+		RequestHandler l_handler = new AbandonHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new AddHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new BindHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new CompareHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new DeleteHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new ModifyHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new ExtendedHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new ModifyDnHandler( this ) ;
+		m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new SearchHandler( this ) ;
+        m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+
+		l_handler = new UnbindHandler( this ) ;
+        m_handlers.put( l_handler.getRequestType(), l_handler ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Stage Event Handler Implementation.
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Stage Event Handler Implementation for RequestEvents.
+     */
+    class RequestEventHandler extends AbstractEventHandler
+    {
+        /**
+         * Event handler method for processing RequestEvents.
+         *
+         * @param a_event the RequestEvent to process.
+         */
+        public void handleEvent( EventObject a_event )
+        {
+			Request l_request = null ;
+            ClientKey l_clientKey = null ;
+
+            // Throw protocol exception if the event is not a request event.
+            if( ! ( a_event instanceof RequestEvent ) )
+            {
+                throw new ProtocolException(
+                    "Unrecognized event: " + a_event ) ;
+            }
+
+            // Extract the ClientKey and Request parameters from the event
+			l_request = ( ( RequestEvent ) a_event ).getRequest() ;
+            l_clientKey = ( ClientKey )
+                ( ( RequestEvent ) a_event ).getSource() ;
+            m_clientManager.threadAssociate( l_clientKey ) ;
+            m_clientManager.threadAssociate( l_clientKey ) ;
+
+			// Get the handler if we have one defined.
+			RequestHandler l_handler = ( RequestHandler )
+                m_handlers.get( l_request.getType() ) ;
+			if( l_handler == null )
+            {
+                throw new ProtocolException( "Unknown request message type: "
+                    + l_request.getType() ) ;
+            }
+
+            // Based on the handler type start request handling.
+            switch( l_handler.getHandlerType().getValue() )
+            {
+            case( HandlerTypeEnum.NOREPLY_VAL ):
+                NoReplyHandler l_noreply = ( NoReplyHandler ) l_handler ;
+            	l_noreply.handle( l_request ) ;
+                break ;
+            case( HandlerTypeEnum.SINGLEREPLY_VAL ):
+                SingleReplyHandler l_single = ( SingleReplyHandler ) l_handler ;
+            	doSingleReply( l_single, ( SingleReplyRequest ) l_request ) ;
+                break ;
+            case( HandlerTypeEnum.SEARCH_VAL ):
+                SearchHandler l_search = ( SearchHandler ) l_handler ;
+				l_search.handle( ( SearchRequest ) l_request ) ;
+                break ;
+            default:
+                throw new ProtocolException( "Unrecognized handler type: "
+                    + l_handler.getRequestType() ) ;
+            }
+
+            m_clientManager.threadDisassociate() ;
+        }
+    }
+
+
+    private void doSingleReply( SingleReplyHandler a_handler,
+        SingleReplyRequest a_request )
+    {
+        int l_id = a_request.getMessageId() ;
+        LdapResult l_result = null ;
+        ResultResponse l_response = null ;
+
+        try
+        {
+			l_response = a_handler.handle( a_request ) ;
+        }
+
+        // If the individual handlers do not do a global catch and report this
+        // will sheild the server from complete failure on a request reporting
+        // at a minimum the stack trace that cause the request to fail.
+        catch( Throwable t )
+        {
+            switch( a_request.getResponseType().getValue() )
+            {
+            case( MessageTypeEnum.ADDRESPONSE_VAL ):
+				l_response = new AddResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.BINDRESPONSE_VAL ):
+                l_response = new BindResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.COMPARERESPONSE_VAL ):
+				l_response = new CompareResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.DELRESPONSE_VAL ):
+                l_response = new DeleteResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.EXTENDEDRESP_VAL ):
+               	l_response = new ExtendedResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.MODDNRESPONSE_VAL ):
+                l_response = new ModifyDnResponseImpl( l_id ) ;
+                break ;
+            case( MessageTypeEnum.MODIFYRESPONSE_VAL ):
+                l_response = new ModifyResponseImpl( l_id ) ;
+                break ;
+            }
+
+            // @todo We should be able to email this to LDAPd auto-bug list.
+            // if some of error reporting configuration parameters are set. Or
+            // perhaps this is something best left to a logger customization.
+            String l_msg = "Encountered an operational error while processing "
+                + a_request.getType() + " request. Please report the"
+                + " the following server stack trace to the LDAPd Group:\n"
+                + ExceptionUtil.printStackTrace( t ) ;
+            getLogger().error( l_msg ) ;
+            l_result = new LdapResultImpl( l_response ) ;
+            l_result.setMatchedDn( "" ) ;
+            l_result.setErrorMessage( l_msg ) ;
+            l_result.setResultCode( ResultCodeEnum.OPERATIONSERROR ) ;
+            l_response.setLdapResult( l_result ) ;
+        }
+
+        ClientKey l_clientKey = m_clientManager.getClientKey() ;
+		ResponseEvent l_event = new ResponseEvent( l_clientKey, l_response ) ;
+        m_encoder.responseComposed( l_event ) ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Package Friendly Accessors For Blocks the RequestHandlers depends on
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Package friendly accessor to the EventManager for access by
+     * RequestHandlers within this package.
+     *
+     * @return the ClientManager this module depends on
+     */
+    EventManager getEventManager()
+    {
+        return m_eventManager ;
+    }
+
+
+    /**
+     * Package friendly accessor to the ClientManager for access by
+     * RequestHandlers within this package.
+     *
+     * @return the ClientManager this module depends on
+     */
+    ClientManager getClientManager()
+    {
+        return m_clientManager ;
+    }
+
+
+    /**
+     * Package friendly accessor to the UnifiedBackend for access by
+     * RequestHandlers within this package.
+     *
+     * @return the UnifiedBackend this module depends on
+     */
+    UnifiedBackend getNexus()
+    {
+        return m_nexus ;
+    }
+
+
+    /**
+     * Package friendly accessor to the AuthenticationManager for access by
+     * RequestHandlers within this package.
+     *
+     * @return the AuthenticationManager this module depends on
+     */
+    AuthenticationManager getAuthenticationManager()
+    {
+        return m_authManager ;
+    }
+
+
+    /**
+     * Package friendly accessor to the Encoder for access by
+     * RequestHandlers within this package.
+     *
+     * @return the Encoder this module depends on
+     */
+    Encoder getEncoder()
+    {
+        return m_encoder ;
+    }
+
+
+    /**
+     * Package friendly accessor to the OutputManager for access by
+     * RequestHandlers within this package.
+     *
+     * @return the OutputManager this module depends on
+     */
+    OutputManager getOutputManager()
+    {
+        return m_outputManager ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Package Friendly Utility Methods Used By RequestHandlers
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the javax.naming.Name respresent a distinguished name provided as
+     * a String.
+     *
+     * @param a_dn the distinguished name String.
+     * @return the Name representing the String argument.
+     */
+    Name getName( String a_dn )
+        throws NamingException
+    {
+        if( a_dn == null || a_dn.trim().equals( "" ) )
+        {
+			return new LdapName() ;
+        }
+
+		return m_nexus.getName( a_dn ) ;
+    }
+
+
+    /**
+     * Specifically used for operational errors (a.k.a. unexplained exceptions).
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param t the throwable if any associated with the result.
+     */
+    void setResult( ResultResponse a_response, Name a_dn, Throwable t )
+    {
+        setResult( a_response, ResultCodeEnum.OPERATIONSERROR, a_dn,
+            "Operational error encountered please contact report trace!", t ) ;
+    }
+
+
+    /**
+     * Overload used for successful results.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     */
+    void setResult( ResultResponse a_response, Name a_dn )
+    {
+		setResult( a_response, ResultCodeEnum.SUCCESS, a_dn, null, null ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     */
+    void setResult( ResultResponse a_response, ResultCodeEnum a_resultCode,
+        Name a_dn, String a_msg )
+    {
+		setResult( a_response, a_resultCode, a_dn, a_msg, null ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse when the matched Dn is unknown or irrelavent.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     */
+    void setResult( ResultResponse a_response, ResultCodeEnum a_resultCode,
+        String a_msg, Throwable t )
+    {
+        setResult( a_response, a_resultCode, null, a_msg, t ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     */
+    void setResult( ResultResponse a_response, ResultCodeEnum a_resultCode,
+        Name a_dn, String a_msg, Throwable t )
+    {
+        // Initialize the result object and set it in the response
+		LdapResult l_result = new LdapResultImpl( a_response ) ;
+        a_response.setLdapResult( l_result ) ;
+
+        // Log the error if this result is associated with a non null Throwable,
+        // error message and is not a part of a successful response.
+        if( t != null && a_msg != null &&
+            a_resultCode != ResultCodeEnum.SUCCESS )
+        {
+            getLogger().error( a_msg, t ) ;
+        }
+
+        // Do no error message if all is null
+        if( a_msg == null && t == null )
+        {
+            l_result.setErrorMessage( "" ) ;
+        }
+        // Use a_msg in error message if throwable is null only
+        else if( t == null && a_msg != null )
+        {
+            l_result.setErrorMessage( a_msg ) ;
+        }
+        // Use the stack trace as error message if a_msg is null and debug is on
+        else if( a_msg == null && t != null )
+        {
+            if( getLogger().isDebugEnabled() )
+            {
+            	l_result.setErrorMessage( ExceptionUtil.printStackTrace( t ) ) ;
+            }
+        }
+        // When a_msg and t are not null
+		else
+        {
+            // Only append stack trace if debugging is enabled
+            if( getLogger().isDebugEnabled() )
+            {
+				l_result.setErrorMessage( a_msg
+					+ ExceptionUtil.printStackTrace( t ) ) ;
+            }
+            // Do not append stack trace if debugging is off
+            else
+            {
+				l_result.setErrorMessage( a_msg ) ;
+            }
+        }
+
+
+        l_result.setResultCode( a_resultCode ) ;
+
+        if( a_dn == null )
+        {
+            a_dn = new LdapName() ;
+        }
+
+		try
+        {
+            Name l_matchedDn = m_nexus.getMatchedDn( a_dn ) ;
+            l_result.setMatchedDn( l_matchedDn.toString() ) ;
+        }
+        // Regardless of exception this is an operational error
+        catch( Exception e )
+        {
+            StringBuffer l_buf = new StringBuffer() ;
+            l_buf.append( "Could not find matching Dn for '" ) ;
+            l_buf.append( a_dn ) ;
+            l_buf.append( "' due to operational error: " ) ;
+            l_buf.append( e.getMessage() ) ;
+			String l_msg = l_buf.toString() ;
+
+			l_result.setMatchedDn( "" ) ;
+			l_result.setErrorMessage( l_msg ) ;
+			l_result.setResultCode( ResultCodeEnum.OPERATIONSERROR ) ;
+			getLogger().error( l_msg, e ) ;
+        }
+    }
+
+
+    /**
+     * Utility method to get ahold of an ldap context based on a DN.
+     *
+     * @param a_dn the distinguished name of the ldap entry to get a JNDI context to.
+     * @return the context associated with an entry specified by dn.
+     */
+    public LdapContext getContext( String a_dn )
+        throws NamingException
+    {
+        return getContext( getName( a_dn ) ) ;
+    }
+
+
+    /**
+     * Utility method to get ahold of an ldap context based on a DN.
+     *
+     * @param a_dn the distinguished name of the ldap entry to get a JNDI context to.
+     * @return the context associated with an entry specified by dn.
+     */
+    public LdapContext getContext( Name a_dn )
+        throws NamingException
+    {
+        Hashtable l_env = new Hashtable() ;
+        InitialContext l_initialContext = null ;
+
+        l_env.put( Context.INITIAL_CONTEXT_FACTORY,
+            "org.apache.eve.jndi.ServerContextFactory" ) ;
+	    l_initialContext = new InitialContext( l_env ) ;
+	    return ( LdapContext ) l_initialContext.lookup( a_dn ) ;
+    }
+
+
+    /**
+     * Utility method to get then initial context.
+     *
+     * @return the initial context for the directory.
+     */
+    public InitialContext getInitialContext()
+        throws NamingException
+    {
+        Hashtable l_env = new Hashtable() ;
+        l_env.put( Context.INITIAL_CONTEXT_FACTORY,
+            "org.apache.eve.jndi.ServerContextFactory" ) ;
+	    return new InitialContext( l_env ) ;
+    }
+}
+
+
+
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/RequestHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/RequestHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: RequestHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.MessageTypeEnum ;
+
+
+/**
+ * Root of all request handler types.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface RequestHandler
+{
+    /**
+     * Gets the handler type.
+     *
+     * @return a HandlerTypeEnum constant.
+     */
+    HandlerTypeEnum getHandlerType() ;
+
+    /**
+     * Gets the request message type handled by this handler.
+     *
+     * @return a MessageTypeEnum constant associated with the request message.
+     */
+    MessageTypeEnum getRequestType() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,330 @@
+/*
+ * $Id: SearchHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+
+package org.apache.eve.protocol ;
+
+
+import java.util.Iterator ;
+import java.util.HashSet;
+import java.util.Collections;
+
+import java.io.IOException ;
+import java.io.ByteArrayInputStream ;
+import java.rmi.Naming;
+
+import javax.naming.Name ;
+import javax.naming.NamingException;
+
+import org.apache.ldap.common.Lockable ;
+import org.apache.ldap.common.message.Response ;
+import org.apache.ldap.common.message.SearchRequest ;
+import org.apache.ldap.common.message.ResultCodeEnum ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.LockableAttribute ;
+import org.apache.ldap.common.message.LockableAttributes ;
+import org.apache.ldap.common.message.SearchResponseDone ;
+import org.apache.ldap.common.message.SearchResponseEntry ;
+import org.apache.ldap.common.message.LockableAttributeImpl ;
+import org.apache.ldap.common.message.SearchResponseDoneImpl ;
+import org.apache.ldap.common.message.LockableAttributesImpl ;
+import org.apache.ldap.common.message.SearchResponseEntryImpl ;
+
+import org.apache.eve.backend.Cursor ;
+import org.apache.eve.client.ClientKey ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.ldap.common.message.ScopeEnum ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.schema.Schema;
+
+
+/**
+ * SearchRequest handler.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class SearchHandler
+    implements RequestHandler
+{
+    /** The protocol module this handler is used by */
+    private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a SearchRequest handler instance for use by a ProtocolModule.
+     * 
+     * @param a_module the ProtocolModule this instance is created for.
+     */
+    public SearchHandler( ProtocolModule a_module )
+    {
+        m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // SearchHandler's Primary Handling Method
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Specifically designed handler method for processing SearchRequests
+     *
+     * @param a_request the SearchRequest to handle
+     */
+    public void handle( SearchRequest a_request )
+    {
+    	Name l_base = null ;
+        UnifiedBackend l_nexus = m_module.getNexus() ;
+
+        try
+        {
+            // Get the normalized search base as a Name
+            l_base = m_module.getName( a_request.getBase() ) ;
+
+            // Return NOSUCHOBJECT done response if the search base is not there
+            if( ! l_nexus.hasEntry( l_base ) )
+            {
+                sendSearchDone(a_request, ResultCodeEnum.NOSUCHOBJECT, l_base,
+                	"Search base not found.", null) ;
+            }
+
+            // Get a cursor over the  search results
+            Cursor l_cursor = l_nexus.search( a_request.getFilter(), l_base,
+                a_request.getScope().getValue() ) ;
+
+            // For each LdapEntry send back a SearchResponseEntry PDU to client
+            while( l_cursor.hasMore() )
+            {
+                LdapEntry l_entry = ( LdapEntry ) l_cursor.next() ;
+
+                // Some backends make the suffix a parent/child of itself
+                // so we need to catch a return of the suffix if the base
+                // in a single scoped search.
+                if( l_entry.getNormalizedDN().equals( l_base )
+                    && a_request.getScope() == ScopeEnum.SINGLELEVEL )
+                {
+                    continue ;
+                }
+
+                sendEntry( a_request, l_entry ) ;
+            }
+
+            // Complete search with a successful SearchResponseDone PDU
+            sendSearchDone( a_request, l_base ) ;
+        }
+        catch( Throwable t )
+        {
+            // Sent a search response done to handle any exceptional conditions
+            // that may have been encountered during search request handling.
+            sendSearchDone( a_request, t ) ;
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type for this RequestHandler.
+     *
+     * @return HandlerTypeEnum.SEARCH always
+     */
+    public HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.SEARCH ;
+    }
+
+
+    /**
+     * Gets the message type this handler is designed to respond to.
+     *
+     * @return MessageTypeEnum.SEARCHREQUEST always.
+     */
+    public MessageTypeEnum getRequestType()
+    {
+        return MessageTypeEnum.SEARCHREQUEST ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Utility Methods Used by Search Handler Method
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the attributes view of the entry by copying LdapEntry attributes and
+     * their values into a LockableAttributes object.
+     *
+     * @param  req the search request
+     * @param a_parent the Lockable parent used by the LockableAttributes
+     * @param a_entry the entry to transform into a LockableAttributes instance
+     * @return the LockableAttributes representation of the LdapEntry
+     */
+    private LockableAttributes
+        getAttributes( SearchRequest req, Lockable a_parent, LdapEntry a_entry )
+    {
+		// Create the LockableAttributes using the default implementation
+        LockableAttributes l_attributes =
+            new LockableAttributesImpl( a_parent ) ;
+        Schema schema = null ;
+
+        try
+        {
+            Name ndn = a_entry.getNormalizedDN() ;
+            schema = m_module.getNexus().getSchema(ndn) ;
+        }
+        catch( NamingException e )
+        {
+            m_module.getLogger().error("dn normalization failed", e) ;
+        }
+
+        // Iterate through the set of attributes in the entry.
+        Iterator l_list = a_entry.attributes().iterator() ;
+        while( l_list.hasNext() )
+        {
+            // Get the name/id of the attribute and create a LockableAttribute
+            // using the default implementation and add it to the attributes
+            String l_id = ( String ) l_list.next() ;
+
+            // build a hashtable of requested ids
+            HashSet requestedIds = new HashSet() ;
+            requestedIds.addAll( req.getAttributes() ) ;
+
+            LockableAttribute l_attribute = null ;
+
+            if ( requestedIds.size() == 0 && schema.isOperational(l_id) )
+            {
+                continue ;
+            }
+            else if ( requestedIds.size() != 0 && !requestedIds.contains(l_id) )
+            {
+                continue ;
+            }
+
+            l_attribute = new LockableAttributeImpl( l_attributes, l_id ) ;
+        	l_attributes.put( l_attribute ) ;
+
+            // Add the values of the attribute in the entry to the Attribute
+            Iterator l_values = a_entry.getMultiValue( l_id ).iterator() ;
+            while( l_values.hasNext() )
+            {
+                l_attribute.add( l_values.next() ) ;
+            }
+        }
+
+        return l_attributes ;
+    }
+
+
+    /**
+     * Sends a SearchResponseEntry containing the attributes of an LdapEntry to
+     * the client.
+     *
+     * @param a_request the request to respond to
+     * @param a_entry the LdapEntry to send in the SearchResponseEntry PDU
+     */
+    private void sendEntry( SearchRequest a_request, LdapEntry a_entry )
+    {
+        SearchResponseEntry l_response =
+            new SearchResponseEntryImpl( a_request.getMessageId() ) ;
+        l_response.setObjectName( a_entry.getEntryDN() ) ;
+        l_response.setAttributes( getAttributes( a_request,
+                l_response, a_entry ) ) ;
+        transmit( l_response ) ;
+    }
+
+
+    /**
+     * Sends a SearchResponseDone for a specific error using its result code and
+     * error message.
+     * 
+     * @param a_request the request to respond to
+     * @param a_resultCode the LdapResult result code enumeration to use
+     * @param a_dn the search base which is used to determine the matching Dn
+     * @param a_msg the custom error message to send
+     * @param a_error the error causing the negative response to the client
+     */
+    private void sendSearchDone( SearchRequest a_request,
+        ResultCodeEnum a_resultCode, Name a_dn, String a_msg,
+        Throwable a_error )
+    {
+        SearchResponseDone l_response =
+            new SearchResponseDoneImpl( a_request.getMessageId() ) ;
+        m_module.setResult( l_response, a_resultCode, a_dn, a_msg, a_error ) ;
+        transmit( l_response ) ;
+    }
+
+
+    /**
+     * Sends a SearchResponseDone for a specific error the result code and
+     * error messages may be generated from the type of error that results.  In
+     * a sense this overload is the generic exception handler for this request
+     * handler.
+     * 
+     * @param a_request the request to respond to
+     * @param a_error the error causing the negative response to the client
+     */
+    private void sendSearchDone( SearchRequest a_request, Throwable a_error )
+    {
+        SearchResponseDone l_response =
+            new SearchResponseDoneImpl( a_request.getMessageId() ) ;
+        m_module.setResult( l_response, null, a_error ) ;
+        transmit( l_response ) ;
+    }
+
+
+    /**
+     * Sends a successful SearchResponseDone.
+     * 
+     * @param a_request the request to respond to
+     * @param a_dn the search base which is used to determine the matching Dn
+     */
+    private void sendSearchDone( SearchRequest a_request, Name a_dn )
+    {
+        SearchResponseDone l_response =
+            new SearchResponseDoneImpl( a_request.getMessageId() ) ;
+        m_module.setResult( l_response, a_dn ) ;
+        transmit( l_response ) ;
+    }
+
+
+    /**
+     * Synchronously transmits a response to the client using special
+     * synchronous interfaces on the Encoder and OutputManager.
+     *
+     * @param a_response the response to transmit to the client.
+     */
+    private void transmit( Response a_response )
+    {
+        byte l_buf[] = m_module.getEncoder().encode( a_response ) ;
+        ByteArrayInputStream l_in = new ByteArrayInputStream( l_buf ) ;
+        ClientKey l_clientKey = m_module.getClientManager().getClientKey() ;
+
+        try
+        {
+            m_module.getOutputManager().write( l_clientKey, l_in ) ;
+        }
+        catch( IOException ioe )
+        {
+            m_module.getClientManager().drop( l_clientKey ) ;
+            m_module.getLogger().error(
+                "Failed to transmit pdu to client " + l_clientKey.toString()
+                + ". Client has been dropped." ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchRequestProcessor.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SearchRequestProcessor.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,554 @@
+/*
+ * $Id: SearchRequestProcessor.java,v 1.22 2003/08/22 21:15:56 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+/**
+ *
+ */
+public class SearchRequestProcessor
+//    extends BaseRequestProcessor
+{
+    /** Response type of this request processor class 
+    public static final int RES_TYPE = LDAPMessageChoice.SEARCHRESDONE_CID ;
+
+    private EventManager m_eventManager = null ;
+    private ExprNode m_exprNode = null ;
+    private Name m_baseDN = null ;
+	private UnifiedBackend m_nexus = null ;
+    private Encoder m_encoder = null ;
+    private OutputManager m_outputManager = null ;
+    private LDAPMessage m_response = null ;
+
+
+    /**
+     * Creates and initializes the request processor.
+     *
+    public SearchRequestProcessor(ClientKey a_client, LDAPMessage a_request)
+    {
+        super(a_client, a_request, RES_TYPE) ;
+    }
+
+
+    /**
+     * Processes the request.
+     * dummy to test protocol communication
+     * @see org.apache.eve.protocol.RequestProcessor#process()
+     *
+    public LDAPMessage process()
+    {
+        try {
+            SearchEvent l_event = null ;
+            m_baseDN = m_nexus.getNormalizedName(
+                new String( m_request.protocolOp.searchRequest.baseObject ) ) ;
+            Filter l_filter = m_request.protocolOp.searchRequest.filter ;
+            m_exprNode = ExprTreeComposer.compose( l_filter ) ;
+			SearchControls l_controls = getSearchControls() ;
+
+            if ( m_eventManager.hasListener( 
+                ProtocolEvent.SEARCHREQUEST_MASK ) ) 
+            {
+                l_event = new SearchEvent( this, true ) ;
+                l_event.setBase( m_baseDN ) ;
+                l_event.setFilter( m_exprNode ) ;
+                l_event.setSearchControls( l_controls ) ;
+                m_eventManager.fireBefore( l_event ) ;
+			} 
+            else if ( getLogger().isDebugEnabled() ) 
+            {
+				getLogger().debug( 
+                    "No event listeners for search operations are"
+					+ " enabled - SearchEvent not constucted - not fired before"
+                    + " operation!" ) ;
+			}
+
+            if ( getLogger().isDebugEnabled() ) 
+            {
+                StringBuffer l_buf = new StringBuffer() ;
+                m_exprNode.printToBuffer( l_buf ) ;
+                getLogger().debug( "Entry DN used for search base = '"
+                    + m_baseDN + "'" ) ;
+                getLogger().debug( "ASN1 Filter = " + l_filter ) ;
+                getLogger().debug( "m_exprNode = " + l_buf.toString() ) ;
+                getLogger().debug( "Search scope = " +
+                    getScopeString( m_request.protocolOp.
+                    	searchRequest.scope.value ) ) ;
+            }
+
+            Cursor l_cursor = m_nexus.search( m_exprNode, m_baseDN,
+                l_controls.getSearchScope() ) ;
+            LdapEntry l_candidate = null ;
+            
+            while ( l_cursor.hasMore() ) 
+            {
+                LdapEntry l_entry = ( LdapEntry ) l_cursor.next() ;
+
+				// Filters out special case where some backends return the
+                // base of a single scope search since they map themselves
+                // as their own children.  According to the ldap spec we
+                // should not be returning the base on a single scope search.
+
+                if ( l_controls.getSearchScope() == Backend.SINGLE_SCOPE &&
+                    l_entry.getNormalizedDN().equals( m_baseDN ) )
+                {
+                    if ( getLogger().isDebugEnabled() ) 
+                    {
+                        getLogger().debug( "Not returning base entry with dn '"
+                            + l_entry.getNormalizedDN()
+                            + "' in single scope search." ) ;
+                    }
+
+					continue ;
+                } 
+                else if ( getLogger().isDebugEnabled() ) 
+                {
+                        getLogger().debug( "Returning entry with dn '"
+                            + l_entry.getNormalizedDN()
+                            + "' in single scope search with base '"
+                            + m_baseDN + "'" ) ;
+                }
+
+                if ( getLogger().isDebugEnabled() ) 
+                {
+                    getLogger().debug( getMessageKey()
+                        + " - SearchRequestProcessor.process(): sending entry "
+                        + l_entry.getEntryDN() + " to client" ) ;
+                }
+
+                //if(l_entry.isRefferal()) {
+                //    sendReference(l_entry) ;
+                //} else {
+                    sendEntry(l_entry) ;
+                //}
+            }
+
+			if ( l_event != null ) 
+            {
+                m_eventManager.fireAfter(l_event) ;
+			} 
+            else if ( getLogger().isDebugEnabled() ) 
+            {
+				getLogger().debug(
+                    "No event listeners for search operations are"
+					+ " enabled - SearchEvent not constucted - not fired after"
+                    + " operation!" ) ;
+			}
+
+            return sendDone() ;
+        } 
+        catch ( IllegalArgumentException e ) 
+        {
+            String l_errMsg = "Naming context not found!" ;
+
+            if ( getLogger().isDebugEnabled() ) 
+            {
+                l_errMsg += "\n" + ExceptionUtil.printStackTrace( e ) ;
+            }
+
+			return sendDone( LDAPResultEnum.NAMINGVIOLATION, l_errMsg ) ;
+        } 
+        catch ( Exception e ) 
+        {
+            getLogger().debug( "Failed search request:\n" 
+                + m_request + "\n", e ) ;
+            m_response = new LDAPMessage() ;
+			m_response.messageID = m_request.messageID ;
+            m_response.protocolOp = new LDAPMessageChoice() ;
+            m_response.protocolOp.choiceId = 
+                LDAPMessageChoice.SEARCHRESDONE_CID ;
+            m_response.protocolOp.searchResDone = new SearchResultDone() ;
+            m_response.protocolOp.searchResDone.matchedDN =
+                m_request.protocolOp.searchRequest.baseObject ;
+            m_response.protocolOp.searchResDone.resultCode = 
+                new LDAPResultEnum() ;
+            m_response.protocolOp.searchResDone.resultCode.value =
+                LDAPResultEnum.OPERATIONSERROR ;
+            m_response.protocolOp.searchResDone.errorMessage =
+                "failed on search request!".getBytes() ;
+            return m_response ;
+        }
+    }
+
+
+	public String [] getAttributesToReturn()
+    {
+		AttributeDescriptionList l_adl =
+			m_request.protocolOp.searchRequest.attributes ;
+        String [] l_attribsToReturn = new String [l_adl.size()] ;
+		
+        for ( int ii = 0 ; ii < l_adl.size(); ii++ ) 
+        {
+            l_attribsToReturn[ii] = 
+                new String( ( byte [] ) l_adl.elementAt( ii ) ) ;
+        }
+
+        return l_attribsToReturn ;
+    }
+
+
+    public String getScopeString( int a_scope )
+    {
+		switch ( a_scope ) 
+        {
+		case( SearchRequestEnum.BASEOBJECT ):
+			return "BASE" ;
+		case( SearchRequestEnum.SINGLELEVEL ):
+			return "SINGLE" ;
+		case( SearchRequestEnum.WHOLESUBTREE ):
+			return "SUBTREE" ;
+        default:
+            throw new IllegalArgumentException( 
+            "The scope arg to getScopeString"
+            + " must be a SearchRequestEnum value of BASEOBJECT, SINGLELEVEL,"
+            + " or WHOLESUBTREE." ) ;
+		}
+    }
+
+
+    public SearchControls getSearchControls()
+    {
+        SearchControls l_ctls = new SearchControls() ;
+
+        if ( null != m_request.protocolOp.searchRequest.sizeLimit ) 
+        {
+			l_ctls.setCountLimit( m_request.protocolOp.searchRequest.
+				sizeLimit.longValue() ) ;
+        }
+
+        if ( null != m_request.protocolOp.searchRequest.derefAliases ) 
+        {
+            if ( m_request.protocolOp.searchRequest.derefAliases.value
+                == SearchRequestEnum1.NEVERDEREFALIASES ) 
+            {
+				l_ctls.setDerefLinkFlag( false ) ;
+            } 
+            else 
+            {
+                l_ctls.setDerefLinkFlag( true ) ;
+            }
+        }
+
+        l_ctls.setReturningAttributes( getAttributesToReturn() ) ;
+        l_ctls.setReturningObjFlag( m_request.protocolOp.searchRequest
+            .typesOnly ) ;
+
+        if ( null != m_request.protocolOp.searchRequest.timeLimit ) 
+        {
+			l_ctls.setTimeLimit(m_request.protocolOp.searchRequest.
+				timeLimit.intValue()) ;
+        }
+
+        if ( null != m_request.protocolOp.searchRequest.scope ) 
+        {
+			switch ( m_request.protocolOp.searchRequest.scope.value ) 
+            {
+			case( SearchRequestEnum.BASEOBJECT ):
+				l_ctls.setSearchScope( SearchControls.OBJECT_SCOPE ) ;
+				break ;
+			case( SearchRequestEnum.SINGLELEVEL ):
+				l_ctls.setSearchScope( SearchControls.ONELEVEL_SCOPE ) ;
+				break ;
+			case( SearchRequestEnum.WHOLESUBTREE ):
+				l_ctls.setSearchScope( SearchControls.SUBTREE_SCOPE ) ;
+				break ;
+			default:
+				break ;
+			}
+        }
+
+        return l_ctls ;
+    }
+
+
+    public Name getBaseDN()
+    {
+        return m_baseDN ;
+    }
+
+
+    public byte [] getBaseDNBytes()
+    {
+        return m_request.protocolOp.searchRequest.baseObject ;
+    }
+
+
+    public int getSearchScope()
+    {
+        return m_request.protocolOp.searchRequest.scope.value ;
+    }
+
+
+    public Enumeration getRequestedAttributes()
+    {
+        final AttributeDescriptionList l_adl =
+            m_request.protocolOp.searchRequest.attributes ;
+
+        if ( l_adl.size() < 0 ) 
+        {
+            // Returning empty enum so we don't care about converting binary
+            // bytes to a string nothing comes out of this enumeration.
+            return l_adl.elements() ;
+        }
+
+        final Enumeration l_list = l_adl.elements() ;
+        return new Enumeration() 
+        {
+            public boolean hasMoreElements() 
+            {
+                return l_list.hasMoreElements() ;
+            }
+
+            public Object nextElement() 
+            {
+                String l_retval = 
+                    new String( (byte [] ) l_list.nextElement() ) ;
+
+                if ( getLogger().isDebugEnabled() ) 
+                {
+                    getLogger().debug( "SearchRequest Specified Attribute '"
+                        + l_retval + "'" ) ;
+                }
+
+                return l_retval ;
+            }
+        } ;
+    }
+
+
+    public void sendReference( LdapEntry l_entry )
+    {
+        throw new NotImplementedException() ;
+    }
+
+
+    /**
+     * Synchronous send that does not use asynchronous event based approach.
+     *
+    public void sendEntry( LdapEntry a_entry )
+    {
+        try {
+            LDAPMessage l_pdu = new LDAPMessage() ;
+            l_pdu.messageID = m_request.messageID ;
+    
+            LDAPMessageChoice l_protocolOp = new LDAPMessageChoice() ;
+            l_pdu.protocolOp = l_protocolOp ;
+            l_protocolOp.choiceId = LDAPMessageChoice.SEARCHRESENTRY_CID ;
+            SearchResultEntry l_result = new SearchResultEntry() ;
+            l_protocolOp.searchResEntry = l_result ;
+    
+            l_result.attributes = new PartialAttributeList() ;
+
+            // If entry is the RootDSE then the dn could be null
+            if ( a_entry.getEntryDN() == null ) 
+            {
+                l_result.objectName = "".getBytes() ;
+            } 
+            else 
+            {
+            	l_result.objectName = a_entry.getEntryDN().getBytes() ;
+            }
+
+            addTo( l_result.attributes, a_entry ) ;
+
+            byte [] l_buf = m_encoder.encode( m_client, l_pdu ) ;
+            m_outputManager.write( m_client, 
+                new ByteArrayInputStream( l_buf ) ) ;
+
+            if ( getLogger().isDebugEnabled() ) 
+            {
+                getLogger().debug( getMessageKey()
+                    + " - SearchRequestProcessor.sendEntry(): composed "
+                    + "response for entry "
+                    + a_entry.getEntryDN() + ":\n" + l_pdu ) ;
+            }
+        } 
+        catch( Exception e ) 
+        {
+            getLogger().debug( "Could not send search entry response for entry "
+                + "cadidate:\n" + a_entry, e ) ;
+        }
+    }
+
+
+    LDAPMessage sendDone()
+    {
+        LDAPMessage l_doneMsg = new LDAPMessage() ;
+
+        try {
+            getLogger().debug("search complete sending done response!") ;
+            l_doneMsg.messageID = m_request.messageID ;
+            LDAPMessageChoice l_protocolOp = new LDAPMessageChoice() ;
+            l_protocolOp.choiceId = LDAPMessageChoice.SEARCHRESDONE_CID ;
+            l_doneMsg.protocolOp = l_protocolOp ;
+
+            SearchResultDone l_result = new SearchResultDone() ;
+            l_protocolOp.searchResDone = l_result ;
+            LDAPResultEnum l_enum = new LDAPResultEnum() ;
+            l_result.resultCode = l_enum ;
+            l_enum.value = LDAPResultEnum.SUCCESS ;
+            l_result.errorMessage = "search complete!".getBytes() ;
+            l_result.matchedDN = getBaseDNBytes() ;
+        } catch(Exception e) {
+            getLogger().debug("Cant send search done response.", e) ;
+        }
+
+		return l_doneMsg ;
+    }
+
+
+    LDAPMessage sendDone(int a_resultCode, String a_message)
+    {
+        LDAPMessage l_doneMsg = new LDAPMessage() ;
+
+        try {
+            l_doneMsg.messageID = m_request.messageID ;
+            LDAPMessageChoice l_protocolOp = new LDAPMessageChoice() ;
+            l_protocolOp.choiceId = LDAPMessageChoice.SEARCHRESDONE_CID ;
+            l_doneMsg.protocolOp = l_protocolOp ;
+
+            SearchResultDone l_result = new SearchResultDone() ;
+            l_protocolOp.searchResDone = l_result ;
+            LDAPResultEnum l_enum = new LDAPResultEnum() ;
+            l_result.resultCode = l_enum ;
+            l_enum.value = a_resultCode ;
+            l_result.errorMessage = a_message.getBytes() ;
+            l_result.matchedDN = getBaseDNBytes() ;
+        } catch(Exception e) {
+            getLogger().debug("Cant send search done response.", e) ;
+        }
+
+		return l_doneMsg ;
+    }
+
+
+    /**
+     * dummy to test protocol communication
+     *
+    void addTo( PartialAttributeList a_attribs, LdapEntry a_entry )
+        throws NamingException
+    {
+        boolean l_userSpecified = false ;
+        
+        // List of attributes specified for return by the user
+        Enumeration l_list = getRequestedAttributes() ;
+
+        //
+        // If the attribute description list is empty or null in the request
+        // then we need to return all non-operational attributes rather than
+        // user requested attributes which may request operational attribute
+        // values.
+        //
+
+        if( ! l_list.hasMoreElements() ) 
+        {
+            l_list = Collections.enumeration( a_entry.attributes() ) ;
+            l_userSpecified = false ;
+        }
+        else 
+        {
+            l_userSpecified = true ;
+            
+            if ( getLogger().isDebugEnabled() ) 
+            {
+                StringBuffer l_buf = new StringBuffer() ;
+                l_buf.append( "Looks like the user is asking for specific " ) ;
+                l_buf.append( "attributes to be returned!\nThe requested " ) ;
+                l_buf.append( "attributes are:\n" ) ;
+
+                Enumeration l_attribs = getRequestedAttributes() ;
+                while ( l_attribs.hasMoreElements() ) 
+                {
+                    String l_attrib = ( String ) l_attribs.nextElement() ;
+                    l_buf.append( "\t" ).append( l_attrib ).append( "\n" ) ;
+                }
+                getLogger().debug( l_buf.toString() ) ;
+            }
+        }
+
+
+        PartialAttributeListSeq l_seq = null ;
+        PartialAttributeListSeqSetOf l_seqSet = null ;
+        
+        while ( l_list.hasMoreElements() )
+        {
+            l_seq = new PartialAttributeListSeq() ;
+            String l_name = ( String ) l_list.nextElement() ;
+
+            if ( ! a_entry.hasAttribute( l_name ) ) 
+            {
+                if ( getLogger().isDebugEnabled() ) 
+                {
+                    getLogger().debug( "Attribute '" + l_name + "' does not "
+                        + "exist in entry '" + a_entry.getEntryDN() + "'\n"
+                        + "values will not be returned for this requested "
+                        + "attribute." ) ;
+                }
+
+                continue ;
+            }
+            
+            
+            if ( ! l_userSpecified && 
+                m_nexus.getSchema( m_baseDN ).isOperational( l_name ) )
+            {
+                continue ;
+            }
+            
+
+            l_seq.type = l_name.getBytes() ;
+            l_seqSet = new PartialAttributeListSeqSetOf() ;
+            Iterator l_values = a_entry.getMultiValue( l_name ).iterator() ;
+            while( l_values.hasNext() ) 
+            {
+                Object l_value = l_values.next() ;
+                if ( l_value.getClass().isArray() ) 
+                {
+                    l_seqSet.put( ( byte [] ) l_value, ( byte [] ) l_value ) ;
+                } 
+                else 
+                {
+                    l_seqSet.put( ( ( String ) l_value ).getBytes(),
+                        ( ( String ) l_value ).getBytes() ) ;
+                }
+            }
+
+            l_seq.vals = l_seqSet ;
+            a_attribs.add( l_seq ) ;
+        }
+    }
+
+
+    ////////////////////////
+    // Life-Cycle Methods //
+    ////////////////////////
+
+
+    public void initialize()
+        throws Exception
+    {
+        // Does nothing!
+    }
+
+
+    public void service( ServiceManager a_manager )
+        throws ServiceException
+    {
+        m_nexus = ( UnifiedBackend ) 
+            a_manager.lookup( UnifiedBackend.ROLE ) ;
+        m_encoder = ( Encoder ) 
+            a_manager.lookup( Encoder.ROLE ) ;
+        m_outputManager = ( OutputManager ) 
+            a_manager.lookup( OutputManager.ROLE ) ;
+        m_eventManager = ( EventManager ) 
+            a_manager.lookup( EventManager.ROLE ) ;
+    }
+    */
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SingleReplyHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/SingleReplyHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,44 @@
+/*
+ * $Id: SingleReplyHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+import org.apache.ldap.common.message.SingleReplyRequest ;
+
+
+/**
+ * Request handler signature for those requests that generate a single response
+ * for a request.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface SingleReplyHandler
+    extends RequestHandler
+{
+    /**
+     * Gets the response message type for this SingleReplyHandler.
+     *
+     * @return the MessageTypeEnum constant associated with this handler.
+     */
+    MessageTypeEnum getResponseType() ;
+
+    /**
+     * Handles a request that generates a sole response by returning the
+     * response object back to the caller.
+     *
+     * @param a_request the request to handle.
+     * @return the response to the request argument.
+     */
+    ResultResponse handle( SingleReplyRequest a_request ) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Stats.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Stats.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,97 @@
+/*
+ * $Id: Stats.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.Request ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+
+
+/**
+ * Collects statistics for protocol requests serviced by the server.
+ */
+public class Stats
+{
+	Request m_lastAbandonReq = null ;
+	Request m_lastAddReq = null ;
+	Request m_lastBindReq = null ;
+	Request m_lastCompareReq = null ;
+	Request m_lastDelReq = null ;
+	Request m_lastExtendedReq = null ;
+	Request m_lastModDNReq = null ;
+	Request m_lastModifyReq = null ;
+	Request m_lastSearchReq = null ;
+	Request m_lastUnbindReq = null ;
+	Request m_lastRequest = null ;
+
+	int m_numAbandonReq = 0 ;
+	int m_numAddReq = 0 ;
+	int m_numBindReq = 0 ;
+	int m_numCompareReq = 0 ;
+	int m_numDelReq = 0 ;
+	int m_numExtendedReq = 0 ;
+	int m_numModDNReq = 0 ;
+	int m_numModifyReq = 0 ;
+	int m_numSearchReq = 0 ;
+	int m_numUnbindReq = 0 ;
+	int m_numTotal = 0 ;
+
+
+	public void addRequest( Request a_msg )
+    {
+        m_lastRequest = a_msg ;
+        m_numTotal++ ;
+
+        switch( a_msg.getType().getValue() ) {
+        case( MessageTypeEnum.ABANDONREQUEST_VAL ):
+            m_lastAbandonReq = a_msg ;
+        	m_numAbandonReq++ ;
+            break ;
+        case( MessageTypeEnum.ADDREQUEST_VAL ):
+            m_lastAddReq = a_msg ;
+        	m_numAddReq++ ;
+            break ;
+        case( MessageTypeEnum.BINDREQUEST_VAL ):
+            m_lastBindReq = a_msg ;
+        	m_numBindReq++ ;
+            break ;
+        case( MessageTypeEnum.COMPAREREQUEST_VAL ):
+            m_lastCompareReq = a_msg ;
+        	m_numCompareReq++ ;
+            break ;
+        case( MessageTypeEnum.DELREQUEST_VAL ):
+            m_lastDelReq = a_msg ;
+        	m_numDelReq++ ;
+            break ;
+        case( MessageTypeEnum.EXTENDEDREQ_VAL ):
+            m_lastExtendedReq = a_msg ;
+        	m_numExtendedReq++ ;
+            break ;
+        case( MessageTypeEnum.MODDNREQUEST_VAL ):
+            m_lastModDNReq = a_msg ;
+        	m_numModDNReq++ ;
+            break ;
+        case( MessageTypeEnum.MODIFYREQUEST_VAL ):
+            m_lastModifyReq = a_msg ;
+        	m_numModifyReq++ ;
+            break ;
+        case( MessageTypeEnum.SEARCHREQUEST_VAL ):
+            m_lastSearchReq = a_msg ;
+        	m_numSearchReq++ ;
+            break ;
+        case( MessageTypeEnum.UNBINDREQUEST_VAL ):
+            m_lastUnbindReq = a_msg ;
+        	m_numUnbindReq++ ;
+            break ;
+        default:
+            throw new RuntimeException("Unknown LDAP message type.") ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/UnbindHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/UnbindHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,97 @@
+/*
+ * $Id: UnbindHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol ;
+
+
+import org.apache.ldap.common.message.Request ;
+import org.apache.ldap.common.message.UnbindRequest ;
+import org.apache.ldap.common.message.MessageTypeEnum ;
+
+/**
+ * Handles the processing of UnbindRequests.  Not presently implemented.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public class UnbindHandler
+    implements NoReplyHandler
+{
+    /** Reference to the protocol module this handler is part of */
+	private final ProtocolModule m_module ;
+
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a handler for UnbindRequests to work on behalf of a
+     * ProtocolModule.
+     *
+     * @param a_module the ProtocolModule this handler is part of.
+     */
+	public UnbindHandler( ProtocolModule a_module )
+    {
+		m_module = a_module ;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // RequestHandler Interface Method Implementations
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Gets the handler type for this handler which will always be the
+     * HandlerTypeEnum.NOREPLY enumeration constant.
+     *
+     * @return the HandlerTypeEnum.NOREPLY enumeration constant
+     */
+	public final HandlerTypeEnum getHandlerType()
+    {
+        return HandlerTypeEnum.NOREPLY ;
+    }
+
+
+    /**
+     * Gets the message type handled by this handler which will always be the
+     * MessageTypeEnum.UNBINDREQUEST enumeration constant.
+     *
+     * @return the MessageTypeEnum.UNBINDREQUEST enumeration constant
+     */
+	public MessageTypeEnum getRequestType()
+    {
+        return MessageTypeEnum.UNBINDREQUEST ;
+    }
+
+
+    /**
+     * Handles an unbind request by disconnecting a client and terminating their
+     * session on the server.
+     *
+     * @param a_request the UnbindRequest.
+     * @throws ClassCastException if the a_request argument is not an
+     * UnbindRequest
+     */
+    public void handle( Request a_request )
+    {
+        try
+        {
+			UnbindRequest l_request = ( UnbindRequest) a_request ;
+            m_module.getClientManager().drop() ;
+        }
+        catch( Throwable t )
+        {
+            m_module.getLogger().error( "Failed on UnbindRequest!", t ) ;
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Utils.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/Utils.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,590 @@
+/*
+ * $Id: Utils.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol;
+
+
+import java.util.Hashtable ;
+
+import javax.naming.Name ;
+import javax.naming.Context ;
+import javax.naming.NameParser ;
+import javax.naming.InitialContext ;
+import javax.naming.NamingException ;
+import javax.naming.ldap.LdapContext ;
+
+import org.apache.ldap.common.name.LdapName ;
+import org.apache.ldap.common.message.LdapResult ;
+import org.apache.ldap.common.message.ResultResponse ;
+import org.apache.ldap.common.message.ResultCodeEnum ;
+import org.apache.ldap.common.message.LdapResultImpl ;
+
+import org.apache.avalon.framework.ExceptionUtil ;
+import org.apache.avalon.framework.logger.Logger ;
+
+
+/**
+ * Utility functions used internally within this package by the protocol
+ * engine's handlers.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+class Utils
+{
+	private static Logger s_log ;
+
+
+
+    // ------------------------------------------------------------------------
+    // Package Friendly Utility Methods Used By RequestHandlers
+    // ------------------------------------------------------------------------
+
+
+    static void enableLogging( Logger a_logger )
+    {
+        s_log = a_logger ;
+    }
+
+
+    static Logger getLogger()
+    {
+        return s_log ;
+    }
+
+
+    /**
+     * Gets the javax.naming.Name respresent a distinguished name provided as
+     * a String.
+     *
+     * @param a_dn the distinguished name String.
+     * @return the Name representing the String argument.
+     */
+    static Name getName( String a_dn )
+        throws NamingException
+    {
+        if( a_dn == null || a_dn.trim().equals( "" ) )
+        {
+			return new LdapName() ;
+        }
+
+        InitialContext l_ctx = new InitialContext() ;
+        NameParser l_parser = l_ctx.getNameParser( a_dn ) ;
+		return l_parser.parse( a_dn ) ;
+    }
+
+
+    /**
+     * Attempts to deduce the result code from a prefix within the error message
+     * of the throwable argument.  Defaults to OPERATIONSERROR if no result code
+     * can be resolved.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param t the throwable if any associated with the result.
+     */
+    static void setResult( ResultResponse a_response, String a_dn, Throwable t )
+    {
+        setResult( a_response, getResultCode( t ), a_dn, t ) ;
+    }
+
+
+    /**
+     * Attempts to deduce the result code from a prefix within the error message
+     * of the throwable argument.  Defaults to OPERATIONSERROR if no result code
+     * can be resolved.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param t the throwable if any associated with the result.
+     */
+    static void setResult( ResultResponse a_response, Name a_dn, Throwable t )
+    {
+        setResult( a_response, getResultCode( t ), a_dn, null, t, true ) ;
+    }
+
+
+    /**
+     * Overload used for successful results.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     */
+    static void setResult( ResultResponse a_response, Name a_dn )
+    {
+		setResult( a_response, ResultCodeEnum.SUCCESS, a_dn,
+            null, null, true ) ;
+    }
+
+
+    /**
+     * Overload used for successful results.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     */
+    static void setResult( ResultResponse a_response, String a_dn )
+    {
+		setResult( a_response, ResultCodeEnum.SUCCESS, a_dn,
+            null, null, true ) ;
+    }
+
+
+    /**
+     * Overload used for successful results.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_matchForDn whether or not to resolve a matching dn - if false
+     * then a_dn is used as is.
+     */
+    static void setResult( ResultResponse a_response, Name a_dn,
+        boolean a_matchForDn )
+    {
+		setResult( a_response, ResultCodeEnum.SUCCESS, a_dn,
+            null, null, true ) ;
+    }
+
+
+    /**
+     * Overload used for successful results.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_matchForDn whether or not to resolve a matching dn - if false
+     * then a_dn is used as is.
+     */
+    static void setResult( ResultResponse a_response, String a_dn,
+        boolean a_matchForDn )
+    {
+		setResult( a_response, ResultCodeEnum.SUCCESS, a_dn,
+            null, null, true ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, Name a_dn, String a_msg )
+    {
+		setResult( a_response, a_resultCode, a_dn, a_msg, null, true ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, String a_dn, String a_msg )
+    {
+		setResult( a_response, a_resultCode, a_dn, a_msg, null, true ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse when the matched Dn is unknown or irrelavent.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, String a_msg, Throwable t )
+    {
+        setResult( a_response, a_resultCode, "", a_msg, t, true ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, String a_dn, String a_msg, Throwable t )
+    {
+        setResult( a_response, a_resultCode, a_dn, a_msg, t, true ) ;
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     * @param a_matchForDn whether or not we attempt to find a matching dn for
+     * a_dn.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, String a_dn, String a_msg, Throwable t,
+        boolean a_matchForDn )
+    {
+        // Initialize the result object and set it in the response
+		LdapResult l_result = new LdapResultImpl( a_response ) ;
+        a_response.setLdapResult( l_result ) ;
+
+        // Log the error if this result is associated with a non null Throwable,
+        // error message and is not a part of a successful response.
+        if( t != null && a_msg != null &&
+            a_resultCode != ResultCodeEnum.SUCCESS )
+        {
+            getLogger().error( a_msg, t ) ;
+        }
+
+        // Do no error message if all is null
+        if( a_msg == null && t == null )
+        {
+            l_result.setErrorMessage( "" ) ;
+        }
+        // Use a_msg in error message if throwable is null only
+        else if( t == null && a_msg != null )
+        {
+            l_result.setErrorMessage( a_msg ) ;
+        }
+        // Use the stack trace as error message if a_msg is null and debug is on
+        else if( a_msg == null && t != null )
+        {
+            if( getLogger().isDebugEnabled() )
+            {
+            	l_result.setErrorMessage( ExceptionUtil.printStackTrace( t ) ) ;
+            }
+        }
+        // When a_msg and t are not null
+		else
+        {
+            // Only append stack trace if debugging is enabled
+            if( getLogger().isDebugEnabled() )
+            {
+				l_result.setErrorMessage( a_msg
+					+ ExceptionUtil.printStackTrace( t ) ) ;
+            }
+            // Do not append stack trace if debugging is off
+            else
+            {
+				l_result.setErrorMessage( a_msg ) ;
+            }
+        }
+
+
+        l_result.setResultCode( a_resultCode ) ;
+
+        if( a_dn == null )
+        {
+            a_dn = "" ;
+        }
+
+		try
+        {
+            if( a_matchForDn )
+            {
+            	Name l_matchedDn = getMatchedDn( a_dn ) ;
+                l_result.setMatchedDn( l_matchedDn.toString() ) ;
+            }
+            else
+            {
+                l_result.setMatchedDn( a_dn ) ;
+            }
+        }
+        // Regardless of exception this is an operational error
+        catch( Exception e )
+        {
+            StringBuffer l_buf = new StringBuffer() ;
+            l_buf.append( "Could not find matching Dn for '" ) ;
+            l_buf.append( a_dn ) ;
+            l_buf.append( "' due to operational error: " ) ;
+            l_buf.append( e.getMessage() ) ;
+			String l_msg = l_buf.toString() ;
+
+			l_result.setMatchedDn( "" ) ;
+			l_result.setErrorMessage( l_msg ) ;
+			l_result.setResultCode( ResultCodeEnum.OPERATIONSERROR ) ;
+			getLogger().error( l_msg, e ) ;
+        }
+    }
+
+
+    /**
+     * Utility function that creates and populates an LdapResult into a
+     * ResultResponse. So many places used this same code we had to put
+     * the it into one place as a utility function.
+     *
+     * @param a_response the ResultResponse object to build the result for
+     * @param a_resultCode the returned error code.
+     * @param a_dn the dn associated with the request used to find the
+     * matchingDn for the response.
+     * @param a_msg the error message to use.
+     * @param t the throwable if any associated with the result.
+     */
+    static void setResult( ResultResponse a_response,
+        ResultCodeEnum a_resultCode, Name a_dn, String a_msg,
+        Throwable t, boolean a_matchForDn )
+    {
+        if( a_dn == null )
+        {
+            setResult( a_response, a_resultCode, "", a_msg, t, a_matchForDn ) ;
+        }
+        else
+        {
+        	setResult( a_response, a_resultCode, a_dn.toString(), a_msg,
+                t, a_matchForDn ) ;
+        }
+    }
+
+
+    /**
+     * Utility method to get ahold of an ldap context based on a DN.
+     *
+     * @param a_dn the distinguished name of the ldap entry to get a JNDI context to.
+     * @return the context associated with an entry specified by dn.
+     */
+    static LdapContext getContext( String a_dn )
+        throws NamingException
+    {
+        return getContext( getName( a_dn ) ) ;
+    }
+
+
+    /**
+     * Utility method to get ahold of an ldap context based on a DN.
+     *
+     * @param a_dn the distinguished name of the ldap entry to get a JNDI context to.
+     * @return the context associated with an entry specified by dn.
+     */
+    static LdapContext getContext( Name a_dn )
+        throws NamingException
+    {
+        Hashtable l_env = new Hashtable() ;
+        InitialContext l_initialContext = null ;
+
+        l_env.put( Context.INITIAL_CONTEXT_FACTORY,
+            "org.apache.eve.jndi.ServerContextFactory" ) ;
+	    l_initialContext = new InitialContext( l_env ) ;
+	    return ( LdapContext ) l_initialContext.lookup( a_dn ) ;
+    }
+
+
+    /**
+     * Utility method to get then initial context.
+     *
+     * @return the initial context for the directory.
+     */
+    static InitialContext getInitialContext()
+        throws NamingException
+    {
+        Hashtable l_env = new Hashtable() ;
+        l_env.put( Context.INITIAL_CONTEXT_FACTORY,
+            "org.apache.eve.jndi.ServerContextFactory" ) ;
+	    return new InitialContext( l_env ) ;
+    }
+
+
+    /**
+     * Gets the most significant Dn that exists within the server and hence can
+     * be matched to an actual entry.
+     *
+     * @param a_dn to use for the matching test.
+     * @return the matching portion of a_dn, or the valid empty string dn if no
+     * match was found.
+     */
+	static Name getMatchedDn( String a_dn )
+        throws NamingException
+    {
+        Name l_dn = null ;
+        Context l_ctx = null ;
+        InitialContext l_initCtx = null ;
+
+        // Don't try to match for the empty dn which matches by default
+        if( a_dn == null || a_dn.trim().equals( "" ) )
+        {
+            return new LdapName() ;
+        }
+
+        l_initCtx = getInitialContext() ;
+		l_dn = l_initCtx.getNameParser( a_dn ).parse( a_dn ) ;
+        while( l_dn.size() > 0 )
+        {
+			try
+			{
+				l_ctx = ( Context ) l_initCtx.lookup( l_dn ) ;
+			}
+			catch( NamingException ne )
+			{
+                // Ignore exceptions
+			}
+
+            if( l_ctx == null )
+            {
+            	l_dn.remove( l_dn.size()-1 ) ;
+            }
+            else
+            {
+                return l_dn ;
+            }
+        }
+
+        return l_dn ;
+    }
+
+
+    /**
+     * Gets the most significant Dn that exists within the server and hence can
+     * be matched to an actual entry.
+     *
+     * @param a_dn to use for the matching test.
+     * @return the matching portion of a_dn, or the valid empty string dn if no
+     * match was found.
+     */
+	static Name getMatchedDn( Name a_dn )
+        throws NamingException
+    {
+        Name l_dn = ( Name ) a_dn.clone() ;
+        Context l_ctx = null ;
+        InitialContext l_initCtx = null ;
+
+        // Don't try to match for the empty dn which matches by default
+        if( l_dn.size() == 0 )
+        {
+            return l_dn ;
+        }
+
+        l_initCtx = getInitialContext() ;
+        while( l_dn.size() > 0 )
+        {
+			try
+			{
+				l_ctx = ( Context ) l_initCtx.lookup( l_dn ) ;
+			}
+			catch( NamingException ne )
+			{
+                // Ignore exceptions
+			}
+
+            if( l_ctx == null )
+            {
+            	l_dn.remove( l_dn.size() - 1 ) ;
+            }
+            else
+            {
+                return l_dn ;
+            }
+        }
+
+        return l_dn ;
+    }
+
+
+    /**
+     * Gets the result code embedded within the message of a throwable.  Because
+     * there is a loss of resolution in error codes due to many LDAPv3 result
+     * codes mapping to the same JNDI exception, we need to embed the result
+     * code associated with the error within the exception message.  We cannot
+     * change the JNDI exception to add result code fields.  So if the result
+     * code is embedded it is within the first four characters of the message.
+     * LDAPv3 result codes only go upto 80 so 2 digits are used at the most and
+     * single digit values are padded with zeros in the front.  The '[' and ']'
+     * characters are used to delimit the result code value.  So for example if
+     * the result code is a 51 for the BUSY result code then the message of the
+     * exception is prefixed with '[51]'.  If the result code is a 3 for
+     * TIMELIMITEXCEEDED then the prefix would be '[03]'.
+     *
+     * Note that if the result code extraction process fails due to an number
+     * format exception on the failure to parse the integer value then the
+     * failure is logged as a warning and OPERATIONSERROR is returned.  If the
+     * prefix does not exist it is presumed that the exception was due to an
+     * internal server failure that has no value other than OPERATIONSERROR
+     * associated with it.  Unintentional exceptions not created and thrown by
+     * the code such as NullPointerExceptions hence result in OPERATIONSERRORS.
+     * And if debugging is enabled the entire stack trace eventually is
+     * delivered to the client with a request to report the bug.
+     *
+     * This method extracts the embedded result code string and parses it into
+     * an integer.  It then calls the getResultCode(int) with the integer as the
+     * argument to get the ResultCodeEnum enumeration constant which it then
+     * returns.
+     *
+     * @param t the throwable carrying the embedded result code as a prefix
+     * @return the result code associated with the exception.
+     */
+    static ResultCodeEnum getResultCode( Throwable t )
+    {
+        String l_msg = t.getMessage() ;
+        ResultCodeEnum l_resultCode = null ;
+
+        // Don't try to extract the result code value if the message string is
+        // null or does not have the length to contain the prefix for the code
+        if( l_msg == null || l_msg.length() < 4 )
+        {
+            l_resultCode = ResultCodeEnum.OPERATIONSERROR ;
+        }
+        // Attempt to parse only if we have the starting and ending brackets
+		else if( l_msg.charAt( 0 ) == '[' && l_msg.charAt( 3 ) == ']' )
+        {
+            String l_code = l_msg.substring( 1, 3 ) ;
+
+            try
+            {
+            	int l_enumValue = Integer.parseInt( l_code ) ;
+                l_resultCode = ResultCodeEnum.getResultCodeEnum( l_enumValue ) ;
+            }
+			catch( NumberFormatException nfe )
+            {
+                getLogger().warn( "Found embedded result code field of '"
+                    + l_code + "' within error message however could not parse"
+                    + " result code enumeration value from it." ) ;
+                l_resultCode = ResultCodeEnum.OPERATIONSERROR ;
+            }
+        }
+        // No prefix detected so we set the result code to OPERATIONSERROR
+        else
+        {
+             l_resultCode = ResultCodeEnum.OPERATIONSERROR ;
+        }
+
+        return l_resultCode ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/extended/PayloadHandler.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/protocol/extended/PayloadHandler.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,47 @@
+/*
+ * $Id: PayloadHandler.java,v 1.2 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.protocol.extended ;
+
+
+import javax.naming.NamingException ;
+
+import org.apache.eve.backend.BackendException ;
+
+import org.apache.avalon.framework.logger.LogEnabled ;
+import org.apache.avalon.framework.service.Serviceable ;
+
+
+/**
+ * Interface used by all extended request payload handlers which are special
+ * handlers invoked by the ExtendedRequestHandler itself to deal with responding
+ * to an extended request with an extended response payload.
+ *
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.2 $
+ */
+public interface PayloadHandler
+{
+    /**
+     * Gets the object identifier of the extended request this handler is
+     * designed for.
+     *
+     * @return the OID string.
+     */
+    String getRequestOID() ;
+
+    /**
+     * Handles the extended request by extracting parameters from the payload
+     * and optionally generating a response for the request.
+     */
+    byte [] handle( byte [] a_payload )
+        throws BackendException, NamingException ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/AttributeSpec.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/AttributeSpec.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,126 @@
+/*
+ * $Id: AttributeSpec.java,v 1.4 2003/03/13 18:28:01 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import java.util.ArrayList ;
+import java.util.Collection ;
+
+
+/**
+ * Attribute specification bean used to store the schema information for an
+ * attribute definition.  This class is generated by the schema parser and
+ * populated in part by it during the schema file load phase.  Other properties
+ * of the bean are filled in afterwords in other phases during the
+ * initialization of the schema manager.
+ */
+public class AttributeSpec
+{
+
+    //////////////////////////////
+    // Specification Attributes //
+    //////////////////////////////
+
+    String m_oid ;
+    ArrayList m_nameList = new ArrayList() ;
+    String m_desc ;
+    String m_equality ;
+    String m_substr ;
+    String m_ordering ;
+    String m_syntax ;
+    boolean m_isSingleValue = false ;
+    boolean m_canUserModify = true ;
+    String m_usage ;
+    String m_superClass ;
+
+    ////////////////////////////////////////
+    // Implementation Inferred Attributes //
+    ////////////////////////////////////////
+
+    /** Directly references other child AttributeSpecs */
+    ArrayList m_children = new ArrayList() ;
+
+    /**
+     * Gets the unique IANA registered Object IDentifier (OID) associated with
+     * this attribute specification.
+     *
+     * @return String the object identifier.
+     */
+    public String getOid()
+    {
+        return m_oid ;
+    }
+
+
+    public Collection getAllNames()
+    {
+        return m_nameList ;
+    }
+
+
+    public String getDescription()
+    {
+        return m_desc ;
+    }
+
+
+    public String getEqualityMatch()
+    {
+        return m_equality ;
+    }
+
+
+    public String getSubstrMatch()
+    {
+        return m_substr ;
+    }
+
+
+    public String getOrderingMatch()
+    {
+        return m_ordering ;
+    }
+
+
+    public String getSyntaxOid()
+    {
+        return m_syntax ;
+    }
+
+
+    public boolean isSingleValue()
+    {
+        return m_isSingleValue ;
+    }
+
+
+    public boolean canUserModify()
+    {
+        return m_canUserModify ;
+    }
+
+
+    public String getUsage()
+    {
+        return m_usage ;
+    }
+
+
+    public String getSuperClass()
+    {
+        return m_superClass ;
+    }
+
+
+    public String toString()
+    {
+        return m_oid ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Normalizer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Normalizer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,22 @@
+/*
+ * $Id: Normalizer.java,v 1.4 2003/03/13 18:28:02 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+import javax.naming.NamingException ;
+
+
+/**
+ * Equality matching rule attribute value normalizer.
+ */
+public interface Normalizer
+{
+    String getEqualityMatch() ;
+    String normalize(String a_value)
+        throws NamingException ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ObjectClassSpec.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ObjectClassSpec.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,101 @@
+/*
+ * $Id: ObjectClassSpec.java,v 1.4 2003/03/13 18:28:03 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+package org.apache.eve.schema ;
+
+
+import java.util.Collection ;
+import java.util.ArrayList ;
+
+
+/**
+ * Objectclass specification bean used to store the schema information for an
+ * objectclass definition.  This class is generated by the schema parser and
+ * populated in part by it during the schema file load phase.  Other properties
+ * of the bean are filled in afterwords in other phases during the
+ * initialization of the schema manager.
+ */
+public class ObjectClassSpec
+{
+	public static final int ABSTRACT = 0 ;
+	public static final int AUXILIARY = 1 ;
+	public static final int STRUCTURAL = 2 ;
+
+    /////////////////////////////
+	// Specification Variables //
+    /////////////////////////////
+
+    int type = ABSTRACT ;
+    String oid ;
+    String desc ;
+    ArrayList mayList = new ArrayList() ;
+    ArrayList mustList = new ArrayList() ;
+    ArrayList nameList = new ArrayList() ;
+    ArrayList superClasses = new ArrayList() ;
+
+	//////////////////////////////
+    // Implementation Variables //
+	//////////////////////////////
+
+    /** Directly references other child ObjectClassSpecs */
+	ArrayList m_children = new ArrayList() ;
+
+
+    public String getDesc()
+    {
+        return desc ;
+    }
+
+
+    public Collection getSuperClasses()
+    {
+        return superClasses ;
+    }
+
+
+    public int getType()
+    {
+		return type ;
+    }
+
+
+    public Collection getMustList()
+    {
+        return mustList ;
+    }
+
+
+    public Collection getMayList()
+    {
+        return mayList ;
+    }
+
+
+    public String getOid()
+    {
+        return oid ;
+    }
+
+
+    public Collection getNameList()
+    {
+        return nameList ;
+    }
+
+
+    public Collection getAllNames()
+    {
+        return nameList ;
+    }
+
+
+    public String toString()
+    {
+        return (String) nameList.get(0) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ParserSyntaxChecker.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/ParserSyntaxChecker.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,80 @@
+/*
+ * $Id: ParserSyntaxChecker.java,v 1.4 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+import antlr.Parser ;
+import antlr.ANTLRLexer ;
+import java.io.StringReader ;
+import java.lang.reflect.Constructor ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled ;
+import java.io.Reader ;
+
+
+public class ParserSyntaxChecker
+    extends AbstractLogEnabled
+    implements SyntaxChecker
+{
+    private final String m_syntaxOid ;
+    private Constructor m_lexerConstructor ;
+    private Constructor m_parserConstructor ;
+
+
+    public ParserSyntaxChecker(String a_syntaxOid,
+        Class a_lexerClass, Class a_parserClass)
+    {
+        m_syntaxOid = a_syntaxOid ;
+		Constructor [] l_constructors = a_lexerClass.getConstructors() ;
+		Constructor l_constructor = null ;
+
+		for(int ii = 0; ii < l_constructors.length ; ii++) {
+			l_constructor = l_constructors[ii] ;
+			Class [] params = l_constructor.getParameterTypes() ;
+
+			if(1 == params.length && params[0].equals(Reader.class)) {
+                m_lexerConstructor = l_constructor ;
+                break ;
+			}
+		}
+
+        l_constructors = a_parserClass.getConstructors() ;
+		for(int ii = 0; ii < l_constructors.length ; ii++) {
+			l_constructor = l_constructors[ii] ;
+			Class [] params = l_constructor.getParameterTypes() ;
+
+			if(1 == params.length && params[0].equals(a_lexerClass)) {
+                m_parserConstructor = l_constructor ;
+                break ;
+			}
+		}
+    }
+
+
+    public String getSyntaxOid()
+    {
+        return m_syntaxOid ;
+    }
+
+
+	public boolean isValidSyntax(String a_value)
+    {
+        try {
+            StringReader l_in = new StringReader(a_value) ;
+            Object [] args = new Object[1] ;
+            args[0] = l_in ;
+			ANTLRLexer l_lexer = (ANTLRLexer)
+                m_lexerConstructor.newInstance(args) ;
+            args[0] = l_lexer ;
+            Parser l_parser = (Parser) m_parserConstructor.newInstance(args) ;
+            // Ok we do not know what to do with this yet!
+        } catch(Exception e) {
+        }
+
+        throw new RuntimeException("N O T   I M P L E M E N T E D   Y E T !") ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexNormalizer.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexNormalizer.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,54 @@
+/*
+ * $Id: RegexNormalizer.java,v 1.4 2003/03/13 18:28:05 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+package org.apache.eve.schema ;
+
+import org.apache.oro.text.perl.Perl5Util ;
+
+
+public class RegexNormalizer
+    implements Normalizer
+{
+    final Perl5Util m_perl = new Perl5Util() ;
+    final String [] m_exprArray ;
+    final String m_equalMatch ;
+
+
+    public RegexNormalizer(String an_equalMatch, String [] a_exprArray)
+    {
+        m_equalMatch = an_equalMatch ;
+        m_exprArray = a_exprArray ;
+    }
+
+
+    public String normalize(final String a_value)
+    {
+        String l_canonical = a_value ;
+
+        for(int ii = 0; ii < m_exprArray.length; ii++) {
+            l_canonical = m_perl.substitute(m_exprArray[ii], l_canonical) ;
+        }
+
+        return l_canonical ;
+    }
+
+
+    public String getEqualityMatch()
+    {
+        return m_equalMatch ;
+    }
+
+
+    public String toString()
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+        l_buf.append("RegexNormalizer(").append(m_equalMatch).append(", ") ;
+        l_buf.append(m_exprArray).append(')') ;
+        return l_buf.toString() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexSyntaxChecker.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/RegexSyntaxChecker.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,50 @@
+/*
+ * $Id: RegexSyntaxChecker.java,v 1.3 2003/03/13 18:28:05 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import org.apache.oro.text.perl.Perl5Util ;
+
+
+public class RegexSyntaxChecker
+    implements SyntaxChecker
+{
+    private final String m_syntaxOid ;
+    private final String [] m_expressions ;
+    private final Perl5Util m_perl = new Perl5Util() ;
+
+
+    public RegexSyntaxChecker(String a_syntaxOid, String [] a_matchExprArray)
+    {
+        m_expressions = a_matchExprArray ;
+        m_syntaxOid = a_syntaxOid ;
+    }
+
+
+    public String getSyntaxOid()
+    {
+        return m_syntaxOid ;
+    }
+
+
+    public boolean isValidSyntax(String a_value)
+    {
+        boolean l_match = true ;
+
+        for(int ii = 0; ii < m_expressions.length; ii++) {
+            l_match = l_match && m_perl.match(m_expressions[ii], a_value) ;
+            if(!l_match) {
+                break ;
+            }
+        }
+
+        return l_match ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Schema.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/Schema.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,62 @@
+/*
+ * $Id: Schema.java,v 1.10 2003/08/06 04:34:18 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import java.util.Map ;
+import java.util.HashMap ;
+
+import javax.naming.NameParser ;
+import javax.naming.NamingException ;
+import javax.naming.directory.SchemaViolationException ;
+import javax.naming.directory.InvalidAttributesException ;
+
+import org.apache.ldap.common.ldif.LdifParser ;
+import org.apache.ldap.common.ldif.LdifComposer ;
+import org.apache.eve.backend.LdapEntry ;
+
+
+/**
+ * Primitive representation of a schem interface from the perspective of a
+ * backend.
+ */
+public interface Schema
+{
+    String DN_ATTR = "distinguishedname" ;
+    String EXISTANCE_ATTR = "existance" ;
+    String HIERARCHY_ATTR = "parentid" ;
+
+    Map BINARY_SYNTAX_OIDS = new HashMap() ;
+    Map NUMERIC_SYNTAX_OIDS = new HashMap() ;
+    Map DECIMAL_SYNTAX_OIDS = new HashMap() ;
+
+    String normalize( String an_attributeName, String an_attributeValue )
+        throws NamingException ;
+    Normalizer getNormalizer( String a_key, boolean byName )
+        throws NamingException ; 
+	void check( LdapEntry an_entry )
+        throws SchemaViolationException, InvalidAttributesException ;
+
+    boolean isOperational( String an_attributeName ) ;
+    boolean isMultiValue( String an_attributeName ) ;
+    boolean isSingleValue( String an_attributeName ) ;
+    boolean hasAttribute( String an_attributeName ) ;
+    boolean isValidSyntax( String an_attributeName, Object an_attributeValue ) ;
+    boolean isValidSyntax( String an_attributeName, 
+        Object [] an_attributeValue ) ;
+    boolean isBinary( String an_attributeName ) ;
+    boolean isNumeric( String an_attributeName ) ;
+    boolean isDecimal( String an_attributeName ) ;
+    NameParser getNameParser() ;
+    NameParser getNormalizingParser() ;
+    LdifParser getLdifParser() ;
+    LdifComposer getLdifComposer() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaImpl.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaImpl.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,578 @@
+/*
+ * $Id: SchemaImpl.java,v 1.14 2003/08/06 04:34:18 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import org.apache.eve.schema.Schema ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.ldap.common.ldif.LdifParser ;
+import org.apache.ldap.common.ldif.LdifParserImpl ;
+import org.apache.ldap.common.ldif.LdifComposer ;
+import org.apache.ldap.common.ldif.LdifComposerImpl ;
+
+import javax.naming.NameParser ;
+import javax.naming.directory.SchemaViolationException ;
+import javax.naming.directory.InvalidAttributesException ;
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+
+import org.apache.commons.collections.MultiMap ;
+import org.apache.commons.collections.MultiHashMap ;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import javax.naming.NamingException;
+import org.apache.ldap.common.name.NameComponentNormalizer;
+import org.apache.ldap.common.name.DnParser;
+import java.io.IOException;
+import org.apache.avalon.framework.CascadingRuntimeException;
+
+
+/**
+ * A quick and dirty schema implementation.
+ */
+public class SchemaImpl
+    extends AbstractLogEnabled
+    implements Schema
+{
+    public static boolean debug = false ;
+
+    static {
+        // Octet String
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.40",
+            "1.3.6.1.4.1.1466.115.121.1.40") ;
+        // Certificate Pair
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.10",
+            "1.3.6.1.4.1.1466.115.121.1.10") ;
+        // JPEG File Interchange Format JFIF
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.28",
+            "1.3.6.1.4.1.1466.115.121.1.28") ;
+        // Binary
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.5",
+            "1.3.6.1.4.1.1466.115.121.1.5") ;
+        // Certificate
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.8",
+            "1.3.6.1.4.1.1466.115.121.1.8") ;
+        // Certificate List
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.9",
+            "1.3.6.1.4.1.1466.115.121.1.9") ;
+        // Authentication Password Syntax
+        // (Not all binary but we can treat it as such)
+        BINARY_SYNTAX_OIDS.put("1.3.6.1.4.1.4203.1.1.2",
+            "1.3.6.1.4.1.4203.1.1.2") ;
+
+        // INTEGER 1.3.6.1.4.1.1466.115.121.1.27
+        NUMERIC_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.27",
+            "1.3.6.1.4.1.1466.115.121.1.27") ;
+        // Numeric String 1.3.6.1.4.1.1466.115.121.1.36
+        NUMERIC_SYNTAX_OIDS.put("1.3.6.1.4.1.1466.115.121.1.36",
+            "1.3.6.1.4.1.1466.115.121.1.36") ;
+    }
+
+    Map m_syntaxCheckers = new HashMap() ;
+    Map m_normalizers = new HashMap() ;
+
+    LdifComposer m_ldifComposer = new LdifComposerImpl() ;
+    LdifParser m_ldifParser = new LdifParserImpl() ;
+
+    Map m_attributeByOid = new HashMap() ;
+    Map m_attributeByName = new HashMap() ;
+
+    Map m_attribute2super = new HashMap() ;
+
+	MultiMap m_attribute2objectclass = new MultiHashMap() ;
+    MultiMap m_attribute2subordinates = new MultiHashMap() ;
+
+    Map m_objectClassByName = new HashMap() ;
+    Map m_objectClassByOid = new HashMap() ;
+
+	MultiMap m_objectClass2super = new MultiHashMap() ;
+    MultiMap m_objectClass2subordinates = new MultiHashMap() ;
+
+    DnParser m_normalizingParser = null ;
+    DnParser m_parser = null ;
+
+    /////////////////
+    // Constructor //
+    /////////////////
+
+
+	SchemaImpl()
+    {
+        NameComponentNormalizer l_dnNormalizer = new NameComponentNormalizer() {
+			public String normalizeByName(String a_name, String a_value)
+                throws NamingException
+            {
+                return getNormalizer(a_name, true).normalize(a_value) ;
+            }
+
+
+			public String normalizeByOid(String a_oid, String a_value)
+                throws NamingException
+            {
+                return getNormalizer(a_oid, false).normalize(a_value) ;
+            }
+        } ;
+
+        try {
+            m_parser = new DnParser() ;
+        	m_normalizingParser = new DnParser(l_dnNormalizer) ;
+        } catch(IOException e) {
+            throw new CascadingRuntimeException("Could not initialize DnParser "
+                + "for SchemaImpl ", e) ;
+        }
+    }
+
+
+	//////////////////////
+    // Setup Interfaces //
+	//////////////////////
+
+
+    AttributeSpec getAttributeSpec(String a_key, boolean byName)
+        throws NamingException
+    {
+		AttributeSpec l_spec = null ;
+
+        if(byName) {
+			l_spec = (AttributeSpec) m_attributeByName.get(a_key) ;
+        } else {
+            l_spec = (AttributeSpec) m_attributeByOid.get(a_key) ;
+        }
+
+		if(l_spec == null) {
+			throw new NamingException("Unknown AttributeType "
+				+ a_key) ;
+		}
+
+        return l_spec ;
+    }
+
+
+    void setNormalizers(HashMap a_map)
+    {
+        m_normalizers = a_map ;
+    }
+
+
+    void setSyntaxCheckers(HashMap a_map)
+    {
+        m_syntaxCheckers = a_map ;
+    }
+
+
+    Iterator listAttributeSpecs()
+    {
+        return m_attributeByOid.values().iterator() ;
+    }
+
+
+    Iterator listObjectClassSpecs()
+    {
+        return m_objectClassByOid.values().iterator() ;
+    }
+
+
+    void addSchema(SchemaImpl a_schema)
+    {
+        Iterator l_list = a_schema.listAttributeSpecs() ;
+        while(l_list.hasNext()) {
+            addAttributeSpec((AttributeSpec) l_list.next()) ;
+        }
+
+        l_list = a_schema.listObjectClassSpecs() ;
+        while(l_list.hasNext()) {
+            this.addObjectClassSpec((ObjectClassSpec) l_list.next()) ;
+        }
+    }
+
+
+    void addAttributeSpec(AttributeSpec an_attribute)
+    {
+        if(getLogger().isDebugEnabled() && debug) {
+            getLogger().debug("Adding attribute spec for " +
+                an_attribute.getAllNames()) ;
+        }
+
+        m_attributeByOid.put(an_attribute.getOid(), an_attribute) ;
+
+        Iterator l_list = an_attribute.getAllNames().iterator() ;
+        String l_name = null ;
+        String l_superClass = an_attribute.getSuperClass() ;
+
+        if(l_superClass != null) {
+            l_superClass = l_superClass.toLowerCase() ;
+
+            // Equality matching rule should be inherited by topmost superclass
+            // if not specified.
+            if(null == an_attribute.getEqualityMatch()) {
+                AttributeSpec l_superSpec =
+                    (AttributeSpec) m_attributeByName.get(l_superClass) ;
+
+                if(l_superSpec == null) {
+                    throw new RuntimeException("Attribute spec of super class '"
+                        + l_superClass + "' for attribute '" + an_attribute
+                        + "' was not found") ;
+                } else if(null == l_superSpec.m_equality) {
+                    throw new RuntimeException("Super class " + l_superClass
+                        + " of " + an_attribute + " does not have an equality "
+                        + "matching rule") ;
+                } else {
+                    an_attribute.m_equality = l_superSpec.m_equality ;
+                }
+            }
+        }
+
+        while(l_list.hasNext()) {
+            l_name = ((String) l_list.next()).toLowerCase() ;
+        	m_attributeByName.put(l_name, an_attribute) ;
+
+            if(l_superClass != null) {
+        		m_attribute2super.put(l_name, l_superClass) ;
+                m_attribute2subordinates.put(l_superClass, l_name) ;
+            }
+        }
+    }
+
+
+    void addObjectClassSpec(ObjectClassSpec an_objectClass)
+    {
+        if(getLogger().isDebugEnabled() && debug) {
+            getLogger().debug("Adding objectclass spec for " +
+                an_objectClass.getAllNames()) ;
+        }
+
+        try {
+			m_objectClassByOid.put(an_objectClass.getOid(), an_objectClass) ;
+	
+			Iterator l_list = an_objectClass.getAllNames().iterator() ;
+			String l_name = null ;
+			Iterator l_superClasses =
+                an_objectClass.getSuperClasses().iterator() ;
+			String l_superClass = null ;
+			while(l_list.hasNext()) {
+				l_name = ((String) l_list.next()).toLowerCase() ;
+				m_objectClassByName.put(l_name, an_objectClass) ;
+	
+				while(l_superClasses.hasNext()) {
+					l_superClass =
+                        ((String) l_superClasses.next()).toLowerCase() ;
+					if(l_superClass != null) {
+						m_objectClass2super.put(l_name, l_superClass) ;
+						m_objectClass2subordinates.put(l_superClass, l_name) ;
+					}
+				}
+			}
+        } catch(Exception e) {
+            e.printStackTrace() ;
+        }
+    }
+
+
+    ///////////////////////
+    // Schema Interfaces //
+    ///////////////////////
+
+
+    public boolean isBinary(String an_attributeName)
+    {
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+        return BINARY_SYNTAX_OIDS.containsKey(l_attribute.getSyntaxOid()) ;
+    }
+
+
+    public boolean isNumeric(String an_attributeName)
+    {
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+        return NUMERIC_SYNTAX_OIDS.containsKey(l_attribute.getSyntaxOid()) ;
+    }
+
+
+    public boolean isDecimal(String an_attributeName)
+    {
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+        return DECIMAL_SYNTAX_OIDS.containsKey(l_attribute.getSyntaxOid()) ;
+    }
+
+
+    public LdifComposer getLdifComposer()
+    {
+        return m_ldifComposer ;
+    }
+
+    public LdifParser getLdifParser()
+    {
+        return m_ldifParser ;
+    }
+
+
+    public NameParser getNameParser()
+    {
+        return m_parser ;
+    }
+
+    public NameParser getNormalizingParser()
+    {
+        return m_normalizingParser ;
+    }
+
+
+    public Normalizer getNormalizer(String a_key, boolean byName)
+        throws NamingException
+    {
+        AttributeSpec l_spec = getAttributeSpec(a_key, byName) ;
+        String l_equalityMatch = l_spec.getEqualityMatch() ;
+        if(null == l_equalityMatch) {
+            throw new SchemaViolationException("Attribute " + a_key
+                + " does not have an equality matching rule in its spec") ;
+        }
+
+        /*
+        if(getLogger().isInfoEnabled()) {
+			getLogger().info("SchemaImpl.getNormalizer(): attribute '"
+				+ a_key + "' with equality match '" + l_equalityMatch
+				+ "' has the following normalizer '"
+				+ m_normalizers.get(l_equalityMatch) + "'") ;
+        }
+        */
+
+        return (Normalizer) m_normalizers.get(l_equalityMatch) ;
+    }
+
+
+	public void check(LdapEntry an_entry)
+        throws SchemaViolationException, InvalidAttributesException
+    {
+        throw new RuntimeException("N O T   I M P L E M E N T E D   Y E T !") ;
+    }
+
+
+    public boolean hasAttribute(String an_attributeName)
+    {
+        return m_attributeByName.containsKey(an_attributeName.toLowerCase()) ;
+    }
+    
+    
+    public boolean isOperational( String an_attributeName )
+    {
+        /* 
+         * There are two kinds of operational attributes:
+         *      1). Those defined by the protocol
+         *      2). Those defined by backends for their own use
+         * 
+         * The schema and schema manager should only have to be aware of those
+         * operational attributes that are defined by the protocol.  Backend
+         * specific attributes should be managed by the backend.  Outside of the
+         * backend these attributes are just regular user attributes.  The 
+         * functionality of filtering out operational attributes on search 
+         * entry responses is the job of both the backend and the search 
+         * processing code.  Each should do it for the attributes under its
+         * jurisdiction.  Here we breach this sensible contract by having the
+         * schema manager be aware of backend operational attributes.  
+         * 
+         * TODO this method pretends to know about the special operational 
+         * attributes used by the modjdbm backend and hence is imposing a 
+         * dependency.  The sooner operational or attribute filtering is
+         * implemented within the backend the better.
+         */
+         
+         if ( 
+            an_attributeName.toLowerCase().equals( Schema.DN_ATTR ) ||
+            an_attributeName.toLowerCase().equals( Schema.HIERARCHY_ATTR ) ||
+            an_attributeName.toLowerCase().equals( "parentdn" ) ||
+            an_attributeName.toLowerCase().equals( "entryid" )
+            )
+         {
+             return true ;
+         }
+         
+        AttributeSpec l_attribute = ( AttributeSpec )
+            m_attributeByName.get( an_attributeName.toLowerCase() ) ;
+            
+        if ( l_attribute == null )
+        {
+            return false ;
+        }
+        else if ( l_attribute.getUsage() == null )
+        {
+            return false ;
+        }
+        else if ( l_attribute.getUsage().toLowerCase().equals( "directoryoperation" ) )
+        {
+            return true ;
+        }
+        else 
+        {
+            return false ;
+        }
+    }
+
+
+    public boolean isMultiValue(String an_attributeName)
+    {
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+        return !l_attribute.isSingleValue() ;
+    }
+
+
+    public boolean isSingleValue(String an_attributeName)
+    {
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+        return l_attribute.isSingleValue() ;
+    }
+
+
+    public boolean isValidSyntax(String an_attributeName,
+        Object [] an_attributeValue)
+    {
+        // We need to create regular expressions for the various
+        // syntax types and use them to see if we match.
+        //throw new RuntimeException("N O T   I M P L E M E N T E D   Y E T !") ;
+
+        //getLogger().warn("N O T   I M P L E M E N T E D   Y E T :\n\t" +
+        //    "SchemaImpl.isValidSyntax() ") ;
+        return true ;
+    }
+
+
+    public boolean isValidSyntax(String an_attributeName,
+        Object an_attributeValue)
+    {
+        // We need to create regular expressions for the various
+        // syntax types and use them to see if we match.
+        //throw new RuntimeException("N O T   I M P L E M E N T E D   Y E T !") ;
+
+        // getLogger().warn("N O T   I M P L E M E N T E D   Y E T :\n\t" +
+        //    "SchemaImpl.isValidSyntax() ") ;
+        return true ;
+    }
+
+
+    public String normalize(String an_attributeName, String an_attributeValue)
+        throws NamingException
+    {
+        if(getLogger().isDebugEnabled() && debug) {
+            getLogger().debug("normalize called on attribute " +
+                an_attributeName + " with value " + an_attributeValue) ;
+            getLogger().debug("Normalizer map = " + m_normalizers) ;
+        }
+
+        AttributeSpec l_attribute = (AttributeSpec)
+            m_attributeByName.get(an_attributeName.toLowerCase()) ;
+
+		if(getLogger().isDebugEnabled() && an_attributeName.equals("parentId")
+             && debug)
+        {
+            getLogger().debug("Dumping attribute keys in schema") ;
+            Iterator l_list = m_attributeByName.keySet().iterator() ;
+            while(l_list.hasNext()) {
+                String l_name = (String) l_list.next() ;
+                if(l_name.startsWith("p"))
+                	getLogger().debug(l_name) ;
+            }
+        }
+
+        if(getLogger().isDebugEnabled() && debug) {
+            getLogger().debug("spec for attribute " +
+                an_attributeName + " = " + l_attribute) ;
+            getLogger().debug("Equality Match Rule for attribute " +
+                an_attributeName + " = " + l_attribute.getEqualityMatch()) ;
+        }
+
+        String l_equalityMatch = l_attribute.getEqualityMatch() ;
+        if(null != l_equalityMatch) {
+            l_equalityMatch = l_equalityMatch.toLowerCase() ;
+        } else {
+            if(getLogger().isDebugEnabled() && debug) {
+                getLogger().debug("Equality matching rule not defined for "
+                    + "attribute " + an_attributeName + " returning value '" +
+                    an_attributeValue + "' as is") ;
+            }
+
+            return an_attributeValue ;
+        }
+
+        if(!m_normalizers.containsKey(l_equalityMatch)) {
+            if(getLogger().isDebugEnabled() && debug) {
+                getLogger().debug("Could not find normalizer for attribute "
+                    + an_attributeName + " with equality matching rule "
+                    + l_equalityMatch + " returning value '" +
+                    an_attributeValue + "' as is") ;
+                getLogger().debug(getNormalizerDump()) ;
+            }
+            return an_attributeValue ;
+        }
+
+        Normalizer l_normalizer = (Normalizer)
+            m_normalizers.get(l_attribute.getEqualityMatch().toLowerCase()) ;
+        String l_canonical = l_normalizer.normalize(an_attributeValue) ;
+
+        if(getLogger().isDebugEnabled() && debug) {
+            getLogger().debug("Found normalizer for attribute "
+                + an_attributeName + " returning normalized value '" +
+                l_canonical + "'.") ;
+        }
+
+        return l_canonical ;
+    }
+
+	/** JUST FARTING AROUND */
+    public String toString()
+    {
+        String l_str = "\n\nAttribute Subordinates Map:\n\n"
+            + "==============================================================\n"
+        	+ m_attribute2subordinates.toString() + "\n\n"
+            + "Attribute SuperClass Map: "
+            + "==============================================================\n"
+            + m_attribute2super.toString() + "\n\n"
+            + "Attribute By Name Map: "
+            + "==============================================================\n"
+            + m_attributeByName.toString() + "\n\n"
+            + "Attribute By OID Map: "
+            + "==============================================================\n"
+            + m_attributeByOid.toString()
+			+ "Object Class Subordinates Map:\n\n"
+            + "==============================================================\n"
+        	+ m_objectClass2subordinates.toString() + "\n\n"
+            + "Object Class SuperClass Map: "
+            + "==============================================================\n"
+            + m_objectClass2super.toString() + "\n\n"
+            + "Object Class By Name Map: "
+            + "==============================================================\n"
+            + m_objectClassByName.toString() + "\n\n"
+            + "Object Class By OID Map: "
+            + "==============================================================\n"
+            + m_objectClassByOid.toString() ;
+
+        return l_str ;
+    }
+
+
+	String getNormalizerDump()
+    {
+        StringBuffer l_buf = new StringBuffer() ;
+        l_buf.append("Normalizer Key Dump:\n") ;
+        Iterator l_list = m_normalizers.keySet().iterator() ;
+
+        while(l_list.hasNext()) {
+            l_buf.append("\t").append(l_list.next()).append("\n") ;
+        }
+
+        l_buf.append("\nDump Complete\n") ;
+
+        return l_buf.toString() ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,29 @@
+/*
+ * $Id: SchemaManager.java,v 1.3 2003/03/13 18:28:08 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import javax.naming.NamingException ;
+import javax.naming.InvalidNameException ;
+import javax.naming.NameNotFoundException ;
+
+
+/**
+ * Manages schemas based on namespace.
+ */
+public interface SchemaManager
+{
+	public static final String ROLE = SchemaManager.class.getName() ;
+
+    Schema getSchema(String a_dn)
+        throws NamingException ;
+    Schema getCompleteSchema() ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SchemaModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,444 @@
+/*
+ * $Id: SchemaModule.java,v 1.12 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+import java.io.File;
+import java.io.FileInputStream ;
+import java.io.FileNotFoundException ;
+
+import java.util.HashMap ;
+import java.util.Iterator ;
+
+import javax.naming.NamingException ;
+import javax.naming.NameNotFoundException ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.ldap.common.util.StringTools ;
+
+import antlr.RecognitionException ;
+import antlr.TokenStreamException ;
+
+import org.apache.avalon.phoenix.BlockContext ;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.context.Context ;
+import org.apache.avalon.framework.context.ContextException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+
+/**
+ * Schema manager module/block implementation used to parse schema files and
+ * manage DIB schemas and subschema authoritative areas.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.schema.SchemaManager"
+ * @testcase org.apache.eve.schema.TestSchemaModule
+ */
+public class SchemaModule
+    extends AbstractModule implements SchemaManager
+{
+	public static final String BLOCK_CONFIG_NODE = "schema-manager" ;
+
+    private BlockContext m_context ;
+    /** all schema definitions in one place */
+    private final SchemaImpl m_complete = new SchemaImpl() ;
+    /** syntax OID : SyntaxChecker */
+	private final HashMap m_syntaxCheckerMap = new HashMap() ;
+    /** equality matching rule : Normalizer */
+	private final HashMap m_normalizerMap = new HashMap() ;
+    /** schema name : SchemaImpl */
+    private final HashMap m_schemaFileMap = new HashMap() ;
+    /** suffix : SchemaImpl */
+    private final HashMap m_suffixSchemaMap = new HashMap() ;
+
+
+    public void enableLogging(Logger a_logger)
+    {
+        super.enableLogging(a_logger) ;
+        m_complete.enableLogging(a_logger) ;
+    }
+
+
+    public Schema getCompleteSchema()
+    {
+        return m_complete ;
+    }
+
+
+	public Schema getSchema(String a_dn)
+        throws NamingException
+    {
+		// Give it a try without wasting cycles.
+        if(m_suffixSchemaMap.containsKey(a_dn)) {
+            return (Schema) m_suffixSchemaMap.get(a_dn) ;
+        }
+
+        // Now normalize the DN and try again.
+        String l_canonical = m_complete.normalize(Schema.DN_ATTR, a_dn) ;
+        if(m_suffixSchemaMap.containsKey(a_dn)) {
+            return (Schema) m_suffixSchemaMap.get(a_dn) ;
+        }
+
+        throw new NameNotFoundException("No SAA matches suffix: " + a_dn) ;
+    }
+
+
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+	public String getImplementationName()
+    {
+        return "Schema Manager Module" ;
+    }
+
+
+	public String getImplementationClassName()
+    {
+        return SchemaModule.class.getName() ;
+    }
+
+
+    public void contextualize(Context a_context)
+        throws ContextException
+    {
+        super.contextualize(a_context) ;
+
+        try {
+        	m_context = (BlockContext) a_context ;
+            if(getLogger().isDebugEnabled()) {
+        		getLogger().debug("Got handle on block context with base "
+                    + "directory "
+                    + m_context.getBaseDirectory().getAbsolutePath()) ;
+            }
+        } catch(ClassCastException e) {
+			getLogger().debug("Context is not an instance of BlockContext!") ;
+            throw new ContextException(
+                "Context is not an instance of BlockContext!", e) ;
+        }
+    }
+
+
+    /*
+		    =========================================
+    		E X A M P L E   C O N F I G U R A T I O N
+		    =========================================
+
+	<toptag>
+    	<!-- S T A G E : I  -->
+		<!-- files are parsed first to build m_schemaFileMap -->
+
+    	<schema name="core"
+        	filepath="schema/core.schema" />
+    	<schema name="corba"
+        	filepath="schema/corba.schema" />
+    	<schema name="cosine"
+        	filepath="schema/cosine.schema" />
+    	<schema name="java"
+        	filepath="schema/java.schema" />
+    	<schema name="misc"
+        	filepath="schema/misc.schema" />
+    	<schema name="nis"
+        	filepath="schema/nis.schema" />
+    	<schema name="krb5-kdc"
+        	filepath="schema/krb5-kdc.schema" />
+    	<schema name="inetorgperson"
+        	filepath="schema/inetorgperson.schema" />
+
+    	<!-- S T A G E : II  -->
+		<!-- built-ins: deepTrimToLower, deepTrim, trim, dnNormalize, asis -->
+        <!-- regex version is perl5 -->
+
+		<normalization default="asis">
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreMatch"/>
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreListMatch"/>
+        	<normalizer op="deepTrimToLower" rule="caseIgnoreIA5Match"/>
+        	<normalizer op="deepTrim" rule="caseExactIA5Match"/>
+        	<normalizer op="deepTrim" rule="telephoneNumberMatch"/>
+        	<normalizer op="dnNormalize" rule="distinguishedNameMatch"/>
+
+            <normalizer rule="someNewBogusRule">
+            	<regex value="s/abc/123/g"/>
+            	<regex value="/ /d"/>
+            	<regex value="y/def/DEF/"/>
+            </normalizer>
+        </normalization>
+
+    	<!-- S T A G E : III  -->
+		<!-- built-ins: accept, . . ., TBA -->
+        <!-- regex version is perl5 -->
+		<syntax-checkers default="accept">
+        	<!-- fictitious: matches yes, Yes, YES etc -->
+			<syntax-checker oid="1.2.34.2.1.2.3.4523.1">
+            	<regex value="/yes/i"/>
+            </syntax-checker>
+        </syntax-checkers>
+
+        <!-- S T A G E : IV  -->
+	    <!-- Subschema Administrative Area -->
+	    <SAA dn="dc=sales,dc=example,dc=com">
+	        <schema-ref schema="core"/>
+	        <schema-ref schema="inetorgperson"/>
+        </SAA>
+
+        <!-- Subschema Administrative Area -->
+	    <SAA dn="dc=engineering,dc=example,dc=com">
+	        <schema-ref schema="core"/>
+	        <schema-ref schema="cosine"/>
+	        <schema-ref schema="corba"/>
+	        <schema-ref schema="java"/>
+	        <schema-ref schema="misc"/>
+	        <schema-ref schema="inetorgperson"/>
+        </SAA>
+
+        <!-- Subschema Administrative Area -->
+	    <SAA dn="nisDomain=unix,dc=example,dc=com">
+	        <schema-ref schema="core"/>
+	        <schema-ref schema="cosine"/>
+	        <schema-ref schema="inetorgperson"/>
+	        <schema-ref schema="nis"/>
+        </SAA>
+	</toptag>
+
+	*/
+
+
+	public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+        //
+        // Right now the only way to add these files to the sar is via the
+        // <lib> or <classes> nexted sar directive in the ant build.  This
+        // unfortunately packages the schema files under the
+        // apps/ldapd/SAR-INF/lib directory rather than at the top level.
+        //
+        // I tried to update the sar by using jar to add the schema directory
+        // and its contents to the top level directory but updates fail on jar.
+        //
+
+		String l_baseDir = m_context.getBaseDirectory().getAbsolutePath() ;
+        l_baseDir = l_baseDir + File.separator + "SAR-INF" + File.separator +
+            "lib" ;
+
+		// Stage I:
+        Configuration [] l_schemaNodes = a_config.getChildren("schema") ;
+        String l_schemaName = null ;
+        String l_schemaFile = null ;
+        SchemaImpl l_schema = null ;
+		for(int ii = 0; ii < l_schemaNodes.length; ii++) {
+            l_schemaName = l_schemaNodes[ii].getAttribute("name") ;
+            l_schemaFile = l_baseDir + File.separator +
+                l_schemaNodes[ii].getAttribute("filepath") ;
+            l_schema = parse(l_schemaFile) ;
+            m_complete.addSchema(l_schema) ;
+            m_schemaFileMap.put(l_schemaName, l_schema) ;
+        }
+
+        // Stage II:
+		Configuration [] l_normalizers =
+            a_config.getChild("normalization").getChildren("normalizer") ;
+        String l_rule = null ;
+        Normalizer l_normalizer = null ;
+        for(int ii = 0; ii < l_normalizers.length; ii++) {
+			l_rule = l_normalizers[ii].getAttribute("rule").toLowerCase() ;
+			l_normalizer = buildNormalizer(l_rule, l_normalizers[ii]) ;
+            m_normalizerMap.put(l_rule, l_normalizer) ;
+        }
+
+
+        // Stage III:
+		Configuration [] l_syntaxes =
+            a_config.getChild("syntax-checkers").getChildren("syntax-checker") ;
+        String l_oid = null ;
+		SyntaxChecker l_checker = null ;
+        for(int ii = 0; ii < l_syntaxes.length; ii++) {
+			l_oid = l_syntaxes[ii].getAttribute("oid") ;
+			l_checker = buildSyntaxChecker(l_oid, l_syntaxes[ii]) ;
+            m_syntaxCheckerMap.put(l_oid, l_checker) ;
+        }
+        m_complete.setNormalizers(m_normalizerMap) ;
+        m_complete.setSyntaxCheckers(m_syntaxCheckerMap) ;
+        Iterator l_list = m_schemaFileMap.values().iterator() ;
+        while(l_list.hasNext()) {
+            l_schema = (SchemaImpl) l_list.next() ;
+            l_schema.setNormalizers(m_normalizerMap) ;
+            l_schema.setSyntaxCheckers(m_syntaxCheckerMap) ;
+        }
+
+        // Stage IV:
+        // This stage must be last since we need the normalizers to be able to
+        // process the keys for distinguished names used to refer to a SAA
+        //
+
+	    Configuration [] l_saaNodes = a_config.getChildren("SAA") ;
+        String l_saaDN = null ;
+        for(int ii = 0; ii < l_saaNodes.length; ii++) {
+            try {
+                l_saaDN =
+                    m_complete.normalize(Schema.DN_ATTR,
+                        l_saaNodes[ii].getAttribute("dn")) ;
+            } catch(NamingException e) {
+                throw new ConfigurationException("Failed to normalize SAA DN",
+                    e) ;
+            }
+
+            l_schema = buildSAASchema(l_saaNodes[ii]) ;
+            l_schema.setNormalizers(m_normalizerMap) ;
+            l_schema.setSyntaxCheckers(m_syntaxCheckerMap) ;
+            m_suffixSchemaMap.put(l_saaDN, l_schema) ;
+        }
+    }
+
+
+	SyntaxChecker buildSyntaxChecker(String a_oid, Configuration a_syntaxNode)
+        throws ConfigurationException
+    {
+		Configuration [] l_regexes = a_syntaxNode.getChildren("regex") ;
+        String [] l_exprArray = new String [l_regexes.length] ;
+        for(int ii = 0; ii < l_regexes.length; ii++) {
+            l_exprArray[ii] = l_regexes[ii].getAttribute("value") ;
+        }
+
+        return new RegexSyntaxChecker(a_oid, l_exprArray) ;
+    }
+
+
+	Normalizer buildNormalizer(final String a_rule, Configuration a_node)
+        throws ConfigurationException
+    {
+		// Regex Form:
+		if(null == a_node.getAttribute("op", null)) {
+			Configuration [] l_regexes =
+				a_node.getChildren("regex") ;
+			String [] l_exprArray = new String [l_regexes.length] ;
+
+			for(int jj = 0; jj < l_regexes.length; jj++) {
+				l_exprArray[jj] = l_regexes[jj].getAttribute("value") ;
+			}
+
+            return new RegexNormalizer(a_rule, l_exprArray) ;
+		} else { // Non-Regex Form:
+			String l_op = a_node.getAttribute("op", null) ;
+            if(l_op.equals("deepTrimToLower")) {
+                return new AbstractNormalizer(a_rule, "deepTrimToLower") {
+                    public String normalize(String a_value) {
+                        return StringTools.deepTrimToLower(a_value) ;
+                    }
+                } ;
+            } else if(l_op.equals("deepTrim")) {
+                return new AbstractNormalizer(a_rule, "deepTrim") {
+                    public String normalize(String a_value) {
+                        return StringTools.deepTrim(a_value) ;
+                    }
+                } ;
+            } else if(l_op.equals("dnNormalize")) {
+                return new AbstractNormalizer(a_rule, "dnNormalize") {
+                    public String normalize(String a_value)
+						throws NamingException
+                    {
+                        return m_complete.getNormalizingParser().
+                            parse(a_value).toString() ;
+                    }
+                } ;
+            } else if(l_op.equals("trim")) {
+                return new AbstractNormalizer(a_rule, "trim") {
+                    public String normalize(String a_value) {
+                        return a_value.trim() ;
+                    }
+                } ;
+            } else {
+                return new AbstractNormalizer(a_rule, "asis") {
+                    public String normalize(String a_value) {
+                        return a_value ;
+                    }
+                } ;
+            }
+		}
+    }
+
+
+    public abstract class AbstractNormalizer
+        implements Normalizer
+    {
+        final String m_rule ;
+        final String m_func ;
+
+        AbstractNormalizer(String a_rule, String a_func) {
+            m_rule = a_rule ;
+            m_func = a_func ;
+        }
+
+        public String getEqualityMatch() { return m_rule ; }
+        public String toString() {
+            StringBuffer l_buf = new StringBuffer() ;
+            l_buf.append("Normalizer(Rule: ").append(m_rule) ;
+            l_buf.append(", Function: ").append(m_func).append(')') ;
+            return l_buf.toString() ;
+        }
+    }
+
+
+    SchemaImpl buildSAASchema(Configuration a_saaNode)
+        throws ConfigurationException
+    {
+        SchemaImpl l_saaSchema = new SchemaImpl() ;
+        l_saaSchema.enableLogging(getLogger()) ;
+        SchemaImpl l_fileSchema = null ;
+		Configuration [] l_refs = a_saaNode.getChildren("schema-ref") ;
+        for(int ii = 0; ii < l_refs.length; ii++) {
+            l_fileSchema = (SchemaImpl)
+                m_schemaFileMap.get(l_refs[ii].getAttribute("schema")) ;
+
+            Iterator l_attributes = l_fileSchema.listAttributeSpecs() ;
+			while(l_attributes.hasNext()) {
+                l_saaSchema.addAttributeSpec(
+                    (AttributeSpec) l_attributes.next()) ;
+            }
+
+            Iterator l_objectclasses = l_fileSchema.listObjectClassSpecs() ;
+			while(l_objectclasses.hasNext()) {
+                l_saaSchema.addObjectClassSpec(
+                    (ObjectClassSpec) l_objectclasses.next()) ;
+            }
+        }
+
+        return l_saaSchema ;
+    }
+
+
+    SchemaImpl parse(String a_filename)
+        throws ConfigurationException
+    {
+        SchemaImpl l_schema = null ;
+
+        try {
+			antlrSchemaSyntaxLexer lexer =
+				new antlrSchemaSyntaxLexer( new FileInputStream(a_filename ) ) ;
+			l_schema = new SchemaImpl() ;
+            l_schema.enableLogging(getLogger()) ;
+			antlrSchemaParser l_parser = 
+				new antlrSchemaParser(lexer) ;
+			l_parser.schemafile(l_schema) ;
+        } catch(FileNotFoundException e) {
+            throw new ConfigurationException(a_filename + " not found.", e) ;
+        } catch(TokenStreamException e) {
+            throw new ConfigurationException("parser failed on "
+                + a_filename, e) ;
+        } catch(RecognitionException e) {
+            throw new ConfigurationException("parser failed on "
+                + a_filename, e) ;
+        }
+
+        return l_schema ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SyntaxChecker.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/schema/SyntaxChecker.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,18 @@
+/*
+ * $Id: SyntaxChecker.java,v 1.3 2003/03/13 18:28:09 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.schema ;
+
+
+public interface SyntaxChecker
+{
+
+    String getSyntaxOid() ;
+    boolean isValidSyntax(String a_string) ;
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/security/LdapPrincipal.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/security/LdapPrincipal.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,71 @@
+/*
+ * $Id: LdapPrincipal.java,v 1.1 2003/03/26 02:07:19 jmachols Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.security ;
+
+
+import java.util.Locale ;
+import javax.naming.Name ;
+import java.security.Principal ;
+import org.apache.ldap.common.name.LdapName ;
+
+
+/**
+ * Principal implementation with some extra methods to access the Principal's
+ * locale and get the principal's name as a javax.naming.Name.
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: jmachols $
+ * @version $Revision: 1.1 $
+ */
+public class LdapPrincipal
+    implements Principal
+{
+    public final static String ANONYMOUS = "" ;
+    final Name m_name ;
+    final Locale m_locale ;
+
+
+    public LdapPrincipal()
+    {
+        this(new LdapName(), Locale.getDefault()) ;
+    }
+
+
+    public LdapPrincipal(Name a_name)
+    {
+        this(a_name, Locale.getDefault()) ;
+    }
+
+
+    public LdapPrincipal(Name a_name, Locale a_locale)
+    {
+        m_name = a_name ;
+        m_locale = a_locale ;
+    }
+
+
+    public String getName()
+    {
+        return m_name.toString() ;
+    }
+
+
+    public Name getDn()
+    {
+        return m_name ;
+    }
+
+
+    public Locale getLocale()
+    {
+        return m_locale ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationException.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationException.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,41 @@
+/*
+ * $Id: AuthenticationException.java,v 1.3 2003/03/13 18:28:11 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.security.auth;
+
+import org.apache.avalon.framework.CascadingException;
+
+/** This exception is thrown when failed to authenticate occurred */
+public class AuthenticationException extends CascadingException
+{
+    /** Constructs an Exception without a message. */
+    public AuthenticationException(Throwable a_throwable)
+    {
+        super(a_throwable.getMessage()) ;
+    }
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public AuthenticationException(String message, Throwable a_throwable)
+    {
+        super(message, a_throwable) ;
+    }
+
+    /**
+     * Constructs an Exception with a detailed message.
+     * @param Message The message associated with the exception.
+     */
+    public AuthenticationException(String message)
+    {
+        super(message) ;
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationManager.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,38 @@
+/*
+ * $Id: AuthenticationManager.java,v 1.5 2003/08/22 21:15:56 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.security.auth ;
+
+
+import org.apache.avalon.framework.component.Component ;
+import java.security.Principal ;
+import javax.naming.NamingException ;
+import org.apache.avalon.framework.CascadingException;
+import org.apache.eve.backend.BackendException;
+import javax.naming.Name ;
+import org.apache.eve.security.LdapPrincipal ;
+
+
+/**
+ * A service interface for centralized authentication management.  At this point
+ * this is a very simple stub whose interface will definately change to take
+ * advantage of JAAS LoginModules and stack PAM via Java extended security
+ * serivices.  For now we enable simple clear text authentication for simple
+ * binds via a loginSimple() interface.
+ */
+public interface AuthenticationManager
+    extends Component
+{
+    public static final String ROLE = AuthenticationManager.class.getName() ;
+
+    LdapPrincipal loginSimple( Name a_dn, String a_clearTextPassword )
+        throws AuthenticationException, BackendException, NamingException ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationModule.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/security/auth/AuthenticationModule.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,180 @@
+/*
+ * $Id: AuthenticationModule.java,v 1.8 2003/08/22 21:15:56 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.security.auth ;
+
+
+import java.util.Iterator ;
+import java.security.Principal ;
+
+import javax.naming.Name ;
+import javax.naming.NamingException ;
+import javax.naming.NameNotFoundException ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.backend.LdapEntry ;
+import org.apache.eve.backend.AtomicBackend ;
+import org.apache.eve.security.LdapPrincipal ;
+import org.apache.eve.backend.UnifiedBackend ;
+import org.apache.eve.backend.BackendException ;
+
+import org.apache.avalon.framework.CascadingException ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+
+/**
+ * Authenticates users against the backend.
+ * 
+ * @phoenix:block
+ * @phoenix:service name="org.apache.eve.security.auth.AuthenticationManager"
+ * 
+ * @author <a href="mailto:aok123@bellsouth.net">Alex Karasulu</a>
+ * @author $Author: akarasulu $
+ * @version $Revision: 1.8 $
+ */
+public class AuthenticationModule
+    extends AbstractModule
+    implements AuthenticationManager
+{
+	public static final String SIMPLE_PASSWORD_ATTR = "userPassword" ;
+    /**
+     * @todo Make sure we add a configuration parameter to enable and disable
+     * annonymous binds.
+     */
+	private boolean allowsAnnonymousBind = true ;
+	UnifiedBackend m_nexus = null ;
+
+
+    public LdapPrincipal loginSimple( Name a_dn, String a_password )
+        throws AuthenticationException, BackendException, NamingException
+    {
+        LdapPrincipal l_principal = null ;
+
+        if(a_dn.toString().trim().equals("")) {
+            if(allowsAnnonymousBind) {
+                getLogger().info("Annonymous bind granted!") ;
+				return new LdapPrincipal () ;
+            } else {
+                getLogger().info("Annoymous bind refused!") ;
+                throw new AuthenticationException("Annonymous binds disabled") ;
+            }
+        }
+
+		//
+        // First let's check if the user is a backend admin user before pulling
+        // records.
+        //
+
+        if( m_nexus.isAdminUser( a_dn ) ) {
+            if(getLogger().isDebugEnabled()) {
+                getLogger().debug(a_dn + " is an admin user.") ;
+            }
+
+            String l_password =
+                m_nexus.getBackend( a_dn ).getAdminUserPassword() ;
+
+            if(l_password.equals(a_password)) {
+                l_principal = new LdapPrincipal (a_dn) ;
+                return l_principal ;
+            } else {
+                String l_msg = "Authentication Failed: recognized admin "
+                    + a_dn + " had invalid credentials!" ;
+                getLogger().info(l_msg) ;
+                throw new AuthenticationException(l_msg) ;
+            }
+        } else if(getLogger().isDebugEnabled()) {
+            getLogger().debug(a_dn + " not recognized as an admin user.") ;
+        }
+
+        try {
+			LdapEntry l_entry = m_nexus.read(a_dn) ;
+
+            if(!l_entry.hasAttribute(SIMPLE_PASSWORD_ATTR)) {
+                String l_msg = "Cannot authenticate " + a_dn +
+                    " without a " + SIMPLE_PASSWORD_ATTR + " attribute!" ;
+                getLogger().info(l_msg) ;
+                throw new AuthenticationException(l_msg) ;
+            }
+
+            String l_password = (String)
+                l_entry.getSingleValue(SIMPLE_PASSWORD_ATTR) ;
+
+            if(null == l_password) {
+                String l_msg = "User " + a_dn + " cannot be authenticated with"
+                    + " with a null password!" ;
+                getLogger().info(l_msg) ;
+                throw new AuthenticationException(l_msg) ;
+            }
+
+			if(l_password.equals(a_password)) {
+				l_principal = new LdapPrincipal (a_dn) ;
+            } else {
+                String l_msg = "User " + a_dn + " had invalid credentials!" ;
+                getLogger().info(l_msg) ;
+
+                if(getLogger().isDebugEnabled()) {
+                	getLogger().debug(a_dn + " user provided password = " +
+                        a_password + " entry password = " + l_password) ;
+                }
+
+                throw new AuthenticationException(l_msg) ;
+            }
+        } catch(BackendException e) {
+            getLogger().error("Authentication failure due to backend: ", e) ;
+            throw e ;
+        } catch(NameNotFoundException e) {
+            getLogger().error("Authentication failed: " + a_dn
+                + " does not exist!") ;
+            throw e ;
+        }
+
+        return l_principal ;
+    }
+
+
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+		// Does nothing - no configuration need right now.
+    }
+
+
+    public String getImplementationRole()
+    {
+        return ROLE ;
+    }
+
+
+    public String getImplementationName()
+    {
+        return "Simple Authentication Module" ;
+    }
+
+
+    public String getImplementationClassName()
+    {
+        return this.getClass().getName() ;
+    }
+
+
+    /**
+     * Need handle on the nexus module - the unified backend.
+     *
+     * @phoenix:dependency name="org.apache.eve.backend.UnifiedBackend"
+     */
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+		m_nexus = (UnifiedBackend) a_manager.lookup(UnifiedBackend.ROLE) ;
+    }
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/AbstractStage.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/AbstractStage.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,261 @@
+/*
+ * $Id: AbstractStage.java,v 1.4 2003/08/01 05:41:27 akarasulu Exp $
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.seda ;
+
+
+import java.util.ArrayList ;
+import java.util.LinkedList ;
+import java.util.EventObject ;
+
+import org.apache.excalibur.thread.ThreadPool ;
+import org.apache.avalon.framework.service.ServiceManager ;
+import org.apache.avalon.framework.service.ServiceException ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+import org.apache.avalon.framework.configuration.Configuration ;
+import org.apache.avalon.cornerstone.services.threads.ThreadManager ;
+import org.apache.avalon.framework.configuration.ConfigurationException ;
+
+import org.apache.eve.AbstractModule ;
+import org.apache.eve.event.EventHandler ;
+
+
+/**
+ * We don't follow the SEDA API and over simply most of it.  A stage to us is
+ * the queue as well and hence does not expose itself as a Source no dequeue
+ * mechanism exists.  We will however use queue predicates so that we can
+ * control aspects of the enqueue process.  This will be very interesting to
+ * us while filtering certain requests.  The ACI mechanism can be based on this
+ * there is much potential.
+ *
+ * Our system is very specific and simple.  We do not deal with bulk events
+ * getting enqueued at any one time and do not need the sophistication within
+ * some of the enqueue overloads.
+ *
+ * This stage base class presumes the handler is created by the concrete stage
+ * at some point before the start() method is called.
+ */
+public abstract class AbstractStage
+    extends AbstractModule implements Stage, Runnable
+{
+    private static final long DRIVER_WAIT = 200 ;
+    private LinkedList m_queue = new LinkedList() ;
+    private String m_name = null ;
+    private String m_poolName = null ;
+    private boolean m_running = false ;
+    private ArrayList m_predicates = new ArrayList() ;
+    protected ThreadManager m_threadManager = null ;
+    protected EventHandler m_handler = null ;
+
+
+    ///////////////////////////
+    // Stage Implementations //
+    ///////////////////////////
+
+
+    public void addPredicate(EnqueuePredicate a_predicate)
+    {
+		m_predicates.add(a_predicate) ;
+    }
+
+
+    public void enqueue(final EventObject an_event)
+		throws CascadingRuntimeException
+    {
+		if(!hasStarted()) {
+            throw new CascadingRuntimeException(
+                "Cannot enqueue on a stage that has not been started", null) ;
+        }
+
+        boolean l_isAccepted = true ;
+		for(int ii = 0; ii < m_predicates.size() && l_isAccepted; ii++) {
+        	EnqueuePredicate l_test = (EnqueuePredicate) m_predicates.get(ii) ;
+            l_isAccepted &= l_test.accept(an_event) ;
+        }
+
+        if(l_isAccepted) {
+            if(getLogger().isDebugEnabled()) {
+                getLogger().debug("Enqueue operation accepted. Performing "
+                    + "synchronized push of event " + an_event + " on to stage "
+                    + m_name + " queue.") ;
+            }
+			synchronized(m_queue) {
+                if(getLogger().isDebugEnabled()) {
+                    getLogger().debug("Grabbed lock on queue for event " +
+                        an_event + " push onto queue") ;
+                }
+				m_queue.addFirst(an_event) ;
+				m_queue.notifyAll() ;
+			}
+
+            getLogger().debug("Enqueue operation successfully completed") ;
+        } else {
+            if(getLogger().isInfoEnabled()) {
+				getLogger().info("Stage " + m_name
+                    + " predicates dropped event " +  an_event
+                    + " on enqueue operation") ;
+            }
+        }
+    }
+
+
+	/////////////////////////////
+    // Runnable Implementation //
+    /////////////////////////////
+
+
+    public final void run()
+    {
+        if(getLogger().isDebugEnabled()) {
+            getLogger().debug("Stage " + m_name + " started handler thread") ;
+        }
+
+		while(hasStarted()) {
+			synchronized(m_queue) {
+				if(m_queue.isEmpty()) {
+                    try {
+                    	m_queue.wait(DRIVER_WAIT) ;
+                    } catch(InterruptedException e) {
+                        try { stop() ; } catch (Exception e2) {/*NOT THROWN*/}
+                        getLogger().error("Stage stopped due to driver thread "
+                            + "failure: ", e) ;
+                    }
+                } else {
+                    final EventObject l_event =
+                        (EventObject) m_queue.removeLast() ;
+
+                    if(getLogger().isDebugEnabled()) {
+                        getLogger().debug("Stage " + m_name + " popped event "
+                            + l_event + " for processing") ;
+                    }
+
+					final Runnable l_runnable = new Runnable()
+                    {
+                        public void run()
+                        {
+                            try {
+	                            m_handler.handleEvent(l_event) ;
+                            } catch(Throwable t) {
+                                getLogger().error("Stage " + m_name
+                                    + " failed on event " + l_event
+                                    + " in handler thread", t) ;
+                            }
+                        }
+                    } ;
+
+                    ThreadPool l_pool =
+                        m_threadManager.getThreadPool(m_poolName) ;
+                    l_pool.execute(l_runnable) ;
+                }
+            }
+        }
+    }
+
+
+    ////////////////////////
+    // Life-cycle Methods //
+    ////////////////////////
+
+
+    public void start()
+        throws Exception
+    {
+        super.start() ;
+        (new Thread(this)).start() ;
+    }
+
+
+    public void stop()
+        throws Exception
+    {
+        m_running = false ;
+
+        synchronized(this) {
+            // Wake up the driver thread if it is in a wait state.
+            this.notifyAll() ;
+        }
+
+        // Sleep waiting for our driver thread to terminate!
+        Thread.currentThread().sleep(DRIVER_WAIT) ;
+        super.stop() ;
+    }
+
+
+    public void service(ServiceManager a_manager)
+        throws ServiceException
+    {
+        super.service(a_manager) ;
+        m_threadManager = (ThreadManager)
+            a_manager.lookup(ThreadManager.ROLE) ;
+    }
+
+
+    /*
+        E X A M P L E   C O N F I G
+	<toplevel-blockname-tag>
+        <stage name="protocol-stage" poolname="processors"
+        	handler="org.apache.eve.protocol.ProtocolHandler">
+            <predicate
+            	class="org.apache.eve.protocol.BindPredicate"/>
+            <predicate
+            	class="org.apache.eve.protocol.LoadPredicate"/>
+            <predicate
+            	class="org.apache.eve.protocol.PermissionsPredicate"/>
+        </stage>
+
+		<!-- Other block specific configurations can be handled anywhere -->
+	</toplevel-blockname-tag>
+    */
+
+    public void configure(Configuration a_config)
+        throws ConfigurationException
+    {
+        m_name =
+            a_config.getChild("stage").getAttribute("name") ;
+        m_poolName =
+            a_config.getChild("stage").getAttribute("poolname") ;
+
+        if(null == m_name  ||  null == m_poolName) {
+            throw new ConfigurationException("name or poolname attributes must "
+                + "be supplied for a stage!") ;
+        }
+
+        String l_handlerFQN =
+            a_config.getChild("stage").getAttribute("handler", null) ;
+
+        // If handler is null then we presume that the concrete subclass
+        // will instantiate and initialize the handler by itself.
+        if(l_handlerFQN != null) {
+			try {
+				m_handler =
+					(EventHandler) Class.forName(l_handlerFQN).newInstance() ;
+			} catch(Exception e) {
+				throw new ConfigurationException("Could not instantiate the "
+                    + "event handler for stage " + m_name
+                    + " using the fully qualified event handler class name of "
+                    + l_handlerFQN) ;
+			}
+        }
+
+        Configuration [] l_predicates = a_config.getChildren("predicate") ;
+        for(int ii = 0; ii < l_predicates.length; ii++) {
+            String l_className = l_predicates[ii].getAttribute("class") ;
+
+            try {
+				m_predicates.add((EnqueuePredicate)
+                    Class.forName(l_className).newInstance()) ;
+            } catch(Exception e) {
+				throw new ConfigurationException("Could not instantiate an "
+                    + "enqueue predicate for stage " + m_name
+					+ " using the fully qualified class name of "
+                    + l_handlerFQN) ;
+            }
+        }
+    }
+}

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/EnqueuePredicate.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/EnqueuePredicate.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,22 @@
+/*
+ * $Id: EnqueuePredicate.java,v 1.3 2003/03/13 18:28:14 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.seda ;
+
+import java.util.EventObject ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+public interface EnqueuePredicate
+{
+    public boolean accept(EventObject an_event)
+        throws CascadingRuntimeException ;
+}
+

Added: incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/Stage.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/java/org/apache/eve/seda/Stage.java	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,23 @@
+/*
+ * $Id: Stage.java,v 1.3 2003/03/13 18:28:15 akarasulu Exp $
+ * $Prologue$
+ *
+ * -- (c) LDAPd Group                                                    --
+ * -- Please refer to the LICENSE.txt file in the root directory of      --
+ * -- any LDAPd project for copyright and distribution information.      --
+ *
+ */
+
+package org.apache.eve.seda ;
+
+
+import java.util.EventObject ;
+import org.apache.avalon.framework.CascadingRuntimeException ;
+
+
+public interface Stage
+{
+    void enqueue(EventObject an_event) throws CascadingRuntimeException ;
+    void addPredicate(EnqueuePredicate a_predicate) ;
+}
+

Added: incubator/directory/eve/branches/start/src/ldif/addAll.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/addAll.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,12 @@
+dn: dc=domain,dc=com
+objectclass: dcObject
+dc: domain
+
+
+dn: cn=testuser,dc=domain,dc=com
+objectclass: inetOrgPerson
+cn: testuser
+sn: nobody
+userPassword: dumass
+
+

Added: incubator/directory/eve/branches/start/src/ldif/addRoot.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/addRoot.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,4 @@
+dn: dc=domain,dc=com
+objectclass: dcObject
+dc: domain
+

Added: incubator/directory/eve/branches/start/src/ldif/addTestUser.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/addTestUser.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,7 @@
+dn: cn=testuser,dc=domain,dc=com
+objectclass: inetOrgPerson
+cn: testuser
+sn: nobody
+userPassword: dumass
+
+

Added: incubator/directory/eve/branches/start/src/ldif/example.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/example.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,2786 @@
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# dc=domain,dc=com sample LDIF file
+#
+# Notes:
+#   160 total entries.
+#     1 (objectclass=domain) entry (dc=domain,dc=com).
+#     4 (objectclass=organizationalunit) entries.
+#     5 (objectclass=groupofuniquenames) entries.
+#   150 (objectclass=person) entries (all under	ou=people,dc=domain,dc=com).
+#   
+
+dn: ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: cn=Directory Administrators,ou=Groups,dc=domain,dc=com
+cn: Directory Administrators
+objectclass: top
+objectclass: groupofuniquenames
+ou: Groups
+uniquemember: uid=kvaughan,ou=People,dc=domain,dc=com
+uniquemember: uid=rdaugherty,ou=People,dc=domain,dc=com
+uniquemember: uid=hmiller,ou=People,dc=domain,dc=com
+
+dn: ou=Special Users,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: Special Users
+description: Special Administrative Accounts
+
+# Start from here for netscape iPlanet (SUN One Directory Server)
+
+dn: ou=People,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: People
+
+dn: uid=scarter,ou=People,dc=domain,dc=com
+cn: Sam Carter
+sn: Carter
+givenname: Sam
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: scarter
+mail: scarter@domain.com
+telephonenumber: +1 408 555 4798
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4612
+userpassword: sprain
+
+dn: uid=tmorris,ou=People,dc=domain,dc=com
+cn: Ted Morris
+sn: Morris
+givenname: Ted
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tmorris
+mail: tmorris@domain.com
+telephonenumber: +1 408 555 9187
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4117
+userpassword: irrefutable
+
+dn: uid=kvaughan,ou=People,dc=domain,dc=com
+cn: Kirsten Vaughan
+sn: Vaughan
+givenname: Kirsten
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: kvaughan
+mail: kvaughan@domain.com
+telephonenumber: +1 408 555 5625
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 2871
+userpassword: bribery
+
+dn: uid=abergin,ou=People,dc=domain,dc=com
+cn: Andy Bergin
+sn: Bergin
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: abergin
+mail: abergin@domain.com
+telephonenumber: +1 408 555 8585
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3472
+userpassword: inflict
+
+dn: uid=dmiller,ou=People,dc=domain,dc=com
+cn: David Miller
+sn: Miller
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: dmiller
+mail: dmiller@domain.com
+telephonenumber: +1 408 555 9423
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4135
+userpassword: gosling
+
+dn: uid=gfarmer,ou=People,dc=domain,dc=com
+cn: Gern Farmer
+sn: Farmer
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: gfarmer
+mail: gfarmer@domain.com
+telephonenumber: +1 408 555 6201
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1269
+userpassword: ruling
+
+dn: uid=kwinters,ou=People,dc=domain,dc=com
+cn: Kelly Winters
+sn: Winters
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: kwinters
+mail: kwinters@domain.com
+telephonenumber: +1 408 555 9069
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4178
+userpassword: forsook
+
+dn: uid=trigden,ou=People,dc=domain,dc=com
+cn: Torrey Rigden
+sn: Rigden
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: trigden
+mail: trigden@domain.com
+telephonenumber: +1 408 555 9280
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3584
+userpassword: sensitive
+
+dn: uid=cschmith,ou=People,dc=domain,dc=com
+cn: Chris Schmith
+sn: Schmith
+givenname: Chris
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: cschmith
+mail: cschmith@domain.com
+telephonenumber: +1 408 555 8011
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0416
+userpassword: hypotenuse
+
+dn: uid=jwallace,ou=People,dc=domain,dc=com
+cn: Judy Wallace
+sn: Wallace
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: jwallace
+mail: jwallace@domain.com
+telephonenumber: +1 408 555 0319
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1033
+userpassword: linear
+
+dn: uid=jwalker,ou=People,dc=domain,dc=com
+cn: John Walker
+sn: Walker
+givenname: John
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: jwalker
+mail: jwalker@domain.com
+telephonenumber: +1 408 555 1476
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3915
+userpassword: dogleg
+
+dn: uid=tclow,ou=People,dc=domain,dc=com
+cn: Torrey Clow
+sn: Clow
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: tclow
+mail: tclow@domain.com
+telephonenumber: +1 408 555 8825
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4376
+userpassword: cardreader
+
+dn: uid=rdaugherty,ou=People,dc=domain,dc=com
+cn: Robert Daugherty
+sn: Daugherty
+givenname: Robert
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: rdaugherty
+mail: rdaugherty@domain.com
+telephonenumber: +1 408 555 1296
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0194
+userpassword: apples
+
+dn: uid=jreuter,ou=People,dc=domain,dc=com
+cn: Jayne Reuter
+sn: Reuter
+givenname: Jayne
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: jreuter
+mail: jreuter@domain.com
+telephonenumber: +1 408 555 1122
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 2942
+userpassword: destroy
+
+dn: uid=tmason,ou=People,dc=domain,dc=com
+cn: Torrey Mason
+sn: Mason
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: tmason
+mail: tmason@domain.com
+telephonenumber: +1 408 555 1596
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1124
+userpassword: squatted
+
+dn: uid=bhall,ou=People,dc=domain,dc=com
+cn: Benjamin Hall
+sn: Hall
+givenname: Benjamin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: bhall
+mail: bhall@domain.com
+telephonenumber: +1 408 555 6067
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 2511
+userpassword: oranges
+
+dn: uid=btalbot,ou=People,dc=domain,dc=com
+cn: Brad Talbot
+sn: Talbot
+givenname: Brad
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: btalbot
+mail: btalbot@domain.com
+telephonenumber: +1 408 555 4992
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3532
+userpassword: trident
+
+dn: uid=mward,ou=People,dc=domain,dc=com
+cn: Marcus Ward
+sn: Ward
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: mward
+mail: mward@domain.com
+telephonenumber: +1 408 555 5688
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 1707
+userpassword: normal
+
+dn: uid=bjablons,ou=People,dc=domain,dc=com
+cn: Barbara Jablonski
+sn: Jablonski
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: bjablons
+mail: bjablons@domain.com
+telephonenumber: +1 408 555 8815
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0906
+userpassword: strawberry
+
+dn: uid=jmcFarla,ou=People,dc=domain,dc=com
+cn: Judy McFarland
+sn: McFarland
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: jmcFarla
+mail: jmcFarla@domain.com
+telephonenumber: +1 408 555 2567
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 2359
+userpassword: walnut
+
+dn: uid=llabonte,ou=People,dc=domain,dc=com
+cn: Lee Labonte
+sn: Labonte
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: llabonte
+mail: llabonte@domain.com
+telephonenumber: +1 408 555 0957
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2854
+userpassword: sourdough
+
+dn: uid=jcampaig,ou=People,dc=domain,dc=com
+cn: Jody Campaigne
+sn: Campaigne
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jcampaig
+mail: jcampaig@domain.com
+telephonenumber: +1 408 555 1660
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4385
+userpassword: grapevine
+
+dn: uid=bhal2,ou=People,dc=domain,dc=com
+cn: Barbara Hall
+sn: Hall
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: bhal2
+mail: bhal2@domain.com
+telephonenumber: +1 408 555 4491
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2758
+userpassword: truths
+
+dn: uid=alutz,ou=People,dc=domain,dc=com
+cn: Alexander Lutz
+sn: Lutz
+givenname: Alexander
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: alutz
+mail: alutz@domain.com
+telephonenumber: +1 408 555 6505
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 1327
+userpassword: northward
+
+dn: uid=btalbo2,ou=People,dc=domain,dc=com
+cn: Bjorn Talbot
+sn: Talbot
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: btalbo2
+mail: btalbo2@domain.com
+telephonenumber: +1 408 555 4234
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1205
+userpassword: corduroy
+
+dn: uid=achassin,ou=People,dc=domain,dc=com
+cn: Ashley Chassin
+sn: Chassin
+givenname: Ashley
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: achassin
+mail: achassin@domain.com
+telephonenumber: +1 408 555 9972
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0466
+userpassword: duopolist
+
+dn: uid=hmiller,ou=People,dc=domain,dc=com
+cn: Harry Miller
+sn: Miller
+givenname: Harry
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: hmiller
+mail: hmiller@domain.com
+telephonenumber: +1 408 555 9804
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4304
+userpassword: hillock
+
+dn: uid=jcampai2,ou=People,dc=domain,dc=com
+cn: Jeffrey Campaigne
+sn: Campaigne
+givenname: Jeffrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jcampai2
+mail: jcampai2@domain.com
+telephonenumber: +1 408 555 7393
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 1377
+userpassword: nominee
+
+dn: uid=lulrich,ou=People,dc=domain,dc=com
+cn: Lee Ulrich
+sn: Ulrich
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: lulrich
+mail: lulrich@domain.com
+telephonenumber: +1 408 555 8652
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 0985
+userpassword: attribution
+
+dn: uid=mlangdon,ou=People,dc=domain,dc=com
+cn: Marcus Langdon
+sn: Langdon
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: mlangdon
+mail: mlangdon@domain.com
+telephonenumber: +1 408 555 6249
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4471
+userpassword: threat
+
+dn: uid=striplet,ou=People,dc=domain,dc=com
+cn: Stephen Triplett
+sn: Triplett
+givenname: Stephen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: striplet
+mail: striplet@domain.com
+telephonenumber: +1 408 555 4519
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3083
+userpassword: compactify
+
+dn: uid=gtriplet,ou=People,dc=domain,dc=com
+cn: Gern Triplett
+sn: Triplett
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: gtriplet
+mail: gtriplet@domain.com
+telephonenumber: +1 408 555 2582
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 4023
+userpassword: placeable
+
+dn: uid=jfalena,ou=People,dc=domain,dc=com
+cn: John Falena
+sn: Falena
+givenname: John
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jfalena
+mail: jfalena@domain.com
+telephonenumber: +1 408 555 8133
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1917
+userpassword: nightly
+
+dn: uid=speterso,ou=People,dc=domain,dc=com
+cn: Sue Peterson
+sn: Peterson
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: speterso
+mail: speterso@domain.com
+telephonenumber: +1 408 555 3613
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 3073
+userpassword: quinine
+
+dn: uid=ejohnson,ou=People,dc=domain,dc=com
+cn: Emanuel Johnson
+sn: Johnson
+givenname: Emanuel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ejohnson
+mail: ejohnson@domain.com
+telephonenumber: +1 408 555 3287
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 3737
+userpassword: marketwise
+
+dn: uid=prigden,ou=People,dc=domain,dc=com
+cn: Peter Rigden
+sn: Rigden
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: prigden
+mail: prigden@domain.com
+telephonenumber: +1 408 555 5099
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1271
+userpassword: epiphyseal
+
+dn: uid=bwalker,ou=People,dc=domain,dc=com
+cn: Brad Walker
+sn: Walker
+givenname: Brad
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bwalker
+mail: bwalker@domain.com
+telephonenumber: +1 408 555 5476
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3529
+userpassword: interruptible
+
+dn: uid=kjensen,ou=People,dc=domain,dc=com
+cn: Kurt Jensen
+sn: Jensen
+givenname: Kurt
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: kjensen
+mail: kjensen@domain.com
+telephonenumber: +1 408 555 6127
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1944
+userpassword: regulatory
+
+dn: uid=mlott,ou=People,dc=domain,dc=com
+cn: Mike Lott
+sn: Lott
+givenname: Mike
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: mlott
+mail: mlott@domain.com
+telephonenumber: +1 408 555 2234
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 0498
+userpassword: cognac
+
+dn: uid=cwallace,ou=People,dc=domain,dc=com
+cn: Cecil Wallace
+sn: Wallace
+givenname: Cecil
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: cwallace
+mail: cwallace@domain.com
+telephonenumber: +1 408 555 6438
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0349
+userpassword: quintus
+
+dn: uid=tpierce,ou=People,dc=domain,dc=com
+cn: Tobias Pierce
+sn: Pierce
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tpierce
+mail: tpierce@domain.com
+telephonenumber: +1 408 555 1531
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1383
+userpassword: rascal
+
+dn: uid=rbannist,ou=People,dc=domain,dc=com
+cn: Richard Bannister
+sn: Bannister
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rbannist
+mail: rbannist@domain.com
+telephonenumber: +1 408 555 1833
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0983
+userpassword: demonstrate
+
+dn: uid=bplante,ou=People,dc=domain,dc=com
+cn: Brian Plante
+sn: Plante
+givenname: Brian
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: bplante
+mail: bplante@domain.com
+telephonenumber: +1 408 555 3550
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4654
+userpassword: tangerine
+
+dn: uid=rmills,ou=People,dc=domain,dc=com
+cn: Randy Mills
+sn: Mills
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rmills
+mail: rmills@domain.com
+telephonenumber: +1 408 555 2072
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 3823
+userpassword: condescend
+
+dn: uid=bschneid,ou=People,dc=domain,dc=com
+cn: Benjamin Schneider
+sn: Schneider
+givenname: Benjamin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: bschneid
+mail: bschneid@domain.com
+telephonenumber: +1 408 555 1012
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 4471
+userpassword: biblical
+
+dn: uid=skellehe,ou=People,dc=domain,dc=com
+cn: Sue Kelleher
+sn: Kelleher
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: skellehe
+mail: skellehe@domain.com
+telephonenumber: +1 408 555 3480
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1608
+userpassword: sweltering
+
+dn: uid=brentz,ou=People,dc=domain,dc=com
+cn: Bertram Rentz
+sn: Rentz
+givenname: Bertram
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: brentz
+mail: brentz@domain.com
+telephonenumber: +1 408 555 5526
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0617
+userpassword: diachronic
+
+dn: uid=dsmith,ou=People,dc=domain,dc=com
+cn: Daniel Smith
+sn: Smith
+givenname: Daniel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: dsmith
+mail: dsmith@domain.com
+telephonenumber: +1 408 555 9519
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0368
+userpassword: quantitative
+
+dn: uid=scarte2,ou=People,dc=domain,dc=com
+cn: Stephen Carter
+sn: Carter
+givenname: Stephen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: scarte2
+mail: scarte2@domain.com
+telephonenumber: +1 408 555 6022
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 2013
+userpassword: scooter
+
+dn: uid=dthorud,ou=People,dc=domain,dc=com
+cn: David Thorud
+sn: Thorud
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: dthorud
+mail: dthorud@domain.com
+telephonenumber: +1 408 555 6185
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1128
+userpassword: fulcrum
+
+dn: uid=ekohler,ou=People,dc=domain,dc=com
+cn: Elba Kohler
+sn: Kohler
+givenname: Elba
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: ekohler
+mail: ekohler@domain.com
+telephonenumber: +1 408 555 1926
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 2721
+userpassword: guildhall
+
+dn: uid=lcampbel,ou=People,dc=domain,dc=com
+cn: Laurel Campbell
+sn: Campbell
+givenname: Laurel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: lcampbel
+mail: lcampbel@domain.com
+telephonenumber: +1 408 555 2537
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 2073
+userpassword: impress
+
+dn: uid=tlabonte,ou=People,dc=domain,dc=com
+cn: Tim Labonte
+sn: Labonte
+givenname: Tim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tlabonte
+mail: tlabonte@domain.com
+telephonenumber: +1 408 555 0058
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1426
+userpassword: express
+
+dn: uid=slee,ou=People,dc=domain,dc=com
+cn: Scott Lee
+sn: Lee
+givenname: Scott
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: slee
+mail: slee@domain.com
+telephonenumber: +1 408 555 2335
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 1806
+userpassword: revertive
+
+dn: uid=bfree,ou=People,dc=domain,dc=com
+cn: Bjorn Free
+sn: Free
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: bfree
+mail: bfree@domain.com
+telephonenumber: +1 408 555 8588
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3307
+userpassword: etiquette
+
+dn: uid=tschneid,ou=People,dc=domain,dc=com
+cn: Torrey Schneider
+sn: Schneider
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tschneid
+mail: tschneid@domain.com
+telephonenumber: +1 408 555 7086
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2292
+userpassword: chaperone
+
+dn: uid=prose,ou=People,dc=domain,dc=com
+cn: Paula Rose
+sn: Rose
+givenname: Paula
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: prose
+mail: prose@domain.com
+telephonenumber: +1 408 555 9998
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 0542
+userpassword: regatta
+
+dn: uid=jhunter,ou=People,dc=domain,dc=com
+cn: Janet Hunter
+sn: Hunter
+givenname: Janet
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: jhunter
+mail: jhunter@domain.com
+telephonenumber: +1 408 555 7665
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4856
+userpassword: nanometer
+
+dn: uid=ashelton,ou=People,dc=domain,dc=com
+cn: Alexander Shelton
+sn: Shelton
+givenname: Alexander
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: ashelton
+mail: ashelton@domain.com
+telephonenumber: +1 408 555 1081
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1987
+userpassword: appointe
+
+dn: uid=mmcinnis,ou=People,dc=domain,dc=com
+cn: Marcus Mcinnis
+sn: Mcinnis
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: mmcinnis
+mail: mmcinnis@domain.com
+telephonenumber: +1 408 555 9655
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4818
+userpassword: calcify
+
+dn: uid=falbers,ou=People,dc=domain,dc=com
+cn: Frank Albers
+sn: Albers
+givenname: Frank
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: falbers
+mail: falbers@domain.com
+telephonenumber: +1 408 555 3094
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1439
+userpassword: degradation
+
+dn: uid=mschneid,ou=People,dc=domain,dc=com
+cn: Martin Schneider
+sn: Schneider
+givenname: Martin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mschneid
+mail: mschneid@domain.com
+telephonenumber: +1 408 555 5017
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 3153
+userpassword: motorcycle
+
+dn: uid=pcruse,ou=People,dc=domain,dc=com
+cn: Patricia Cruse
+sn: Cruse
+givenname: Patricia
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: pcruse
+mail: pcruse@domain.com
+telephonenumber: +1 408 555 8641
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3967
+userpassword: pauper
+
+dn: uid=tkelly,ou=People,dc=domain,dc=com
+cn: Timothy Kelly
+sn: Kelly
+givenname: Timothy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+l: Santa Clara
+uid: tkelly
+mail: tkelly@domain.com
+telephonenumber: +1 408 555 4295
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3107
+userpassword: risible
+
+dn: uid=ahel,ou=People,dc=domain,dc=com
+cn: Andrew Hel
+sn: Hel
+givenname: Andrew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ahel
+mail: ahel@domain.com
+telephonenumber: +1 408 555 2666
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0572
+userpassword: sarsaparilla
+
+dn: uid=jburrell,ou=People,dc=domain,dc=com
+cn: James Burrell
+sn: Burrell
+givenname: James
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jburrell
+mail: jburrell@domain.com
+telephonenumber: +1 408 555 0751
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4926
+userpassword: degrease
+
+dn: uid=smason,ou=People,dc=domain,dc=com
+cn: Sue Mason
+sn: Mason
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: smason
+mail: smason@domain.com
+telephonenumber: +1 408 555 9780
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4971
+userpassword: sensible
+
+dn: uid=ptyler,ou=People,dc=domain,dc=com
+cn: Pete Tyler
+sn: Tyler
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ptyler
+mail: ptyler@domain.com
+telephonenumber: +1 408 555 3335
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0327
+userpassword: vinegar
+
+dn: uid=calexand,ou=People,dc=domain,dc=com
+cn: Chris Alexander
+sn: Alexander
+givenname: Chris
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: calexand
+mail: calexand@domain.com
+telephonenumber: +1 408 555 9438
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2884
+userpassword: dauphin
+
+dn: uid=jcruse,ou=People,dc=domain,dc=com
+cn: Jim Cruse
+sn: Cruse
+givenname: Jim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jcruse
+mail: jcruse@domain.com
+telephonenumber: +1 408 555 9482
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 0083
+userpassword: bridgework
+
+dn: uid=kcarter,ou=People,dc=domain,dc=com
+cn: Karen Carter
+sn: Carter
+givenname: Karen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: kcarter
+mail: kcarter@domain.com
+telephonenumber: +1 408 555 4675
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 2320
+userpassword: radiosonde
+
+dn: uid=rfish,ou=People,dc=domain,dc=com
+cn: Randy Fish
+sn: Fish
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rfish
+mail: rfish@domain.com
+telephonenumber: +1 408 555 9865
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2317
+userpassword: mailbox
+
+dn: uid=phunt,ou=People,dc=domain,dc=com
+cn: Philip Hunt
+sn: Hunt
+givenname: Philip
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: phunt
+mail: phunt@domain.com
+telephonenumber: +1 408 555 1242
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 1183
+userpassword: wastewater
+
+dn: uid=rschneid,ou=People,dc=domain,dc=com
+cn: Rachel Schneider
+sn: Schneider
+givenname: Rachel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rschneid
+mail: rschneid@domain.com
+telephonenumber: +1 408 555 9908
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4183
+userpassword: decorous
+
+dn: uid=bjensen,ou=People,dc=domain,dc=com
+cn: Barbara Jensen
+cn: Babs Jensen
+sn: Jensen
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: bjensen
+mail: bjensen@domain.com
+telephonenumber: +1 408 555 1862
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0209
+userpassword: hifalutin
+
+dn: uid=jlange,ou=People,dc=domain,dc=com
+cn: Jim Lange
+sn: Lange
+givenname: Jim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: jlange
+mail: jlange@domain.com
+telephonenumber: +1 408 555 0488
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3798
+userpassword: chastity
+
+dn: uid=rulrich,ou=People,dc=domain,dc=com
+cn: Randy Ulrich
+sn: Ulrich
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: rulrich
+mail: rulrich@domain.com
+telephonenumber: +1 408 555 5311
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1282
+userpassword: twinkle
+
+dn: uid=rfrancis,ou=People,dc=domain,dc=com
+cn: Richard Francis
+sn: Francis
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rfrancis
+mail: rfrancis@domain.com
+telephonenumber: +1 408 555 8157
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3482
+userpassword: hacienda
+
+dn: uid=mwhite,ou=People,dc=domain,dc=com
+cn: Morgan White
+sn: White
+givenname: Morgan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mwhite
+mail: mwhite@domain.com
+telephonenumber: +1 408 555 9620
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3088
+userpassword: staple
+
+dn: uid=gjensen,ou=People,dc=domain,dc=com
+cn: Gern Jensen
+sn: Jensen
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: gjensen
+mail: gjensen@domain.com
+telephonenumber: +1 408 555 3299
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4609
+userpassword: primitive
+
+dn: uid=awhite,ou=People,dc=domain,dc=com
+cn: Alan White
+sn: White
+givenname: Alan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: awhite
+mail: awhite@domain.com
+telephonenumber: +1 408 555 3232
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0142
+userpassword: placeholder
+
+dn: uid=bmaddox,ou=People,dc=domain,dc=com
+cn: Barbara Maddox
+sn: Maddox
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bmaddox
+mail: bmaddox@domain.com
+telephonenumber: +1 408 555 7783
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 2207
+userpassword: feedback
+
+dn: uid=mtalbot,ou=People,dc=domain,dc=com
+cn: Martin Talbot
+sn: Talbot
+givenname: Martin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: mtalbot
+mail: mtalbot@domain.com
+telephonenumber: +1 408 555 9228
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1415
+userpassword: currant
+
+dn: uid=jbrown,ou=People,dc=domain,dc=com
+cn: Judy Brown
+sn: Brown
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jbrown
+mail: jbrown@domain.com
+telephonenumber: +1 408 555 6885
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4224
+userpassword: militiamen
+
+dn: uid=jjensen,ou=People,dc=domain,dc=com
+cn: Jody Jensen
+sn: Jensen
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: jjensen
+mail: jjensen@domain.com
+telephonenumber: +1 408 555 7587
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4882
+userpassword: borderland
+
+dn: uid=mcarter,ou=People,dc=domain,dc=com
+cn: Mike Carter
+sn: Carter
+givenname: Mike
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: mcarter
+mail: mcarter@domain.com
+telephonenumber: +1 408 555 1846
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3819
+userpassword: mainland
+
+dn: uid=dakers,ou=People,dc=domain,dc=com
+cn: David Akers
+sn: Akers
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: dakers
+mail: dakers@domain.com
+telephonenumber: +1 408 555 4812
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4944
+userpassword: integument
+
+dn: uid=sfarmer,ou=People,dc=domain,dc=com
+cn: Scott Farmer
+sn: Farmer
+givenname: Scott
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: sfarmer
+mail: sfarmer@domain.com
+telephonenumber: +1 408 555 4228
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0019
+userpassword: triumphal
+
+dn: uid=dward,ou=People,dc=domain,dc=com
+cn: Daniel Ward
+sn: Ward
+givenname: Daniel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: dward
+mail: dward@domain.com
+telephonenumber: +1 408 555 5322
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3927
+userpassword: armload
+
+dn: uid=tward,ou=People,dc=domain,dc=com
+cn: Tobias Ward
+sn: Ward
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: tward
+mail: tward@domain.com
+telephonenumber: +1 408 555 7202
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2238
+userpassword: cedilla
+
+dn: uid=pshelton,ou=People,dc=domain,dc=com
+cn: Patricia Shelton
+sn: Shelton
+givenname: Patricia
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Cupertino
+uid: pshelton
+mail: pshelton@domain.com
+telephonenumber: +1 408 555 6442
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2918
+userpassword: nosedive
+
+dn: uid=jrentz,ou=People,dc=domain,dc=com
+cn: Jody Rentz
+sn: Rentz
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jrentz
+mail: jrentz@domain.com
+telephonenumber: +1 408 555 5829
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3025
+userpassword: meander
+
+dn: uid=plorig,ou=People,dc=domain,dc=com
+cn: Peter Lorig
+sn: Lorig
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: plorig
+mail: plorig@domain.com
+telephonenumber: +1 408 555 0624
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1276
+userpassword: calorimeter
+
+dn: uid=ajensen,ou=People,dc=domain,dc=com
+cn: Allison Jensen
+sn: Jensen
+givenname: Allison
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: ajensen
+mail: ajensen@domain.com
+telephonenumber: +1 408 555 7892
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 0784
+userpassword: coltsfoot
+
+dn: uid=kschmith,ou=People,dc=domain,dc=com
+cn: Kelly Schmith
+sn: Schmith
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: kschmith
+mail: kschmith@domain.com
+telephonenumber: +1 408 555 9749
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 2221
+userpassword: purvey
+
+dn: uid=pworrell,ou=People,dc=domain,dc=com
+cn: Pete Worrell
+sn: Worrell
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: pworrell
+mail: pworrell@domain.com
+telephonenumber: +1 408 555 1637
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 2449
+userpassword: solicitous
+
+dn: uid=mreuter,ou=People,dc=domain,dc=com
+cn: Matthew Reuter
+sn: Reuter
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: mreuter
+mail: mreuter@domain.com
+telephonenumber: +1 408 555 6879
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 1356
+userpassword: oblivious
+
+dn: uid=gtyler,ou=People,dc=domain,dc=com
+cn: Gern Tyler
+sn: Tyler
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: gtyler
+mail: gtyler@domain.com
+telephonenumber: +1 408 555 1020
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0312
+userpassword: typology
+
+dn: uid=tschmith,ou=People,dc=domain,dc=com
+cn: Tobias Schmith
+sn: Schmith
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tschmith
+mail: tschmith@domain.com
+telephonenumber: +1 408 555 9626
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4607
+userpassword: compost
+
+dn: uid=bjense2,ou=People,dc=domain,dc=com
+cn: Bjorn Jensen
+sn: Jensen
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bjense2
+mail: bjense2@domain.com
+telephonenumber: +1 408 555 5655
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4294
+userpassword: mortgage
+
+dn: uid=dswain,ou=People,dc=domain,dc=com
+cn: Dietrich Swain
+sn: Swain
+givenname: Dietrich
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Sunnyvale
+uid: dswain
+mail: dswain@domain.com
+telephonenumber: +1 408 555 9222
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4396
+userpassword: freedom
+
+dn: uid=ahall,ou=People,dc=domain,dc=com
+cn: Andy Hall
+sn: Hall
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ahall
+mail: ahall@domain.com
+telephonenumber: +1 408 555 6169
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3050
+userpassword: slater
+
+dn: uid=jmuffly,ou=People,dc=domain,dc=com
+cn: Jeff Muffly
+sn: Muffly
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jmuffly
+mail: jmuffly@domain.com
+telephonenumber: +1 408 555 5287
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 0997
+userpassword: dictate
+
+dn: uid=tjensen,ou=People,dc=domain,dc=com
+cn: Ted Jensen
+sn: Jensen
+givenname: Ted
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tjensen
+mail: tjensen@domain.com
+telephonenumber: +1 408 555 8622
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4717
+userpassword: ecosystem
+
+dn: uid=ahunter,ou=People,dc=domain,dc=com
+cn: Allison Hunter
+sn: Hunter
+givenname: Allison
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Sunnyvale
+uid: ahunter
+mail: ahunter@domain.com
+telephonenumber: +1 408 555 7713
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1213
+userpassword: egregious
+
+dn: uid=jgoldste,ou=People,dc=domain,dc=com
+cn: Jon Goldstein
+sn: Goldstein
+givenname: Jon
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jgoldste
+mail: jgoldste@domain.com
+telephonenumber: +1 408 555 5769
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1454
+userpassword: yellow
+
+dn: uid=aworrell,ou=People,dc=domain,dc=com
+cn: Alan Worrell
+sn: Worrell
+givenname: Alan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: aworrell
+mail: aworrell@domain.com
+telephonenumber: +1 408 555 1591
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 3966
+userpassword: gargoyle
+
+dn: uid=wlutz,ou=People,dc=domain,dc=com
+cn: Wendy Lutz
+sn: Lutz
+givenname: Wendy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: wlutz
+mail: wlutz@domain.com
+telephonenumber: +1 408 555 3358
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4912
+userpassword: bassinet
+
+dn: uid=jlutz,ou=People,dc=domain,dc=com
+cn: Janet Lutz
+sn: Lutz
+givenname: Janet
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jlutz
+mail: jlutz@domain.com
+telephonenumber: +1 408 555 4902
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2544
+userpassword: autumn
+
+dn: uid=dlangdon,ou=People,dc=domain,dc=com
+cn: Dan Langdon
+sn: Langdon
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: dlangdon
+mail: dlangdon@domain.com
+telephonenumber: +1 408 555 7044
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3263
+userpassword: botulin
+
+dn: uid=aknutson,ou=People,dc=domain,dc=com
+cn: Ashley Knutson
+sn: Knutson
+givenname: Ashley
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: aknutson
+mail: aknutson@domain.com
+telephonenumber: +1 408 555 2169
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4736
+userpassword: maltose
+
+dn: uid=kmcinnis,ou=People,dc=domain,dc=com
+cn: Kelly Mcinnis
+sn: Mcinnis
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: kmcinnis
+mail: kmcinnis@domain.com
+telephonenumber: +1 408 555 8596
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4312
+userpassword: stargaze
+
+dn: uid=tcouzens,ou=People,dc=domain,dc=com
+cn: Trent Couzens
+sn: Couzens
+givenname: Trent
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tcouzens
+mail: tcouzens@domain.com
+telephonenumber: +1 408 555 8401
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3994
+userpassword: tambourine
+
+dn: uid=lstockto,ou=People,dc=domain,dc=com
+cn: Lee Stockton
+sn: Stockton
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: lstockto
+mail: lstockto@domain.com
+telephonenumber: +1 408 555 0518
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0169
+userpassword: brooklyn
+
+dn: uid=jbourke,ou=People,dc=domain,dc=com
+cn: Jon Bourke
+sn: Bourke
+givenname: Jon
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jbourke
+mail: jbourke@domain.com
+telephonenumber: +1 408 555 8541
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0034
+userpassword: brainwash
+
+dn: uid=dlanoway,ou=People,dc=domain,dc=com
+cn: Dan Lanoway
+sn: Lanoway
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: dlanoway
+mail: dlanoway@domain.com
+telephonenumber: +1 408 555 2017
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3540
+userpassword: manhattan
+
+dn: uid=kcope,ou=People,dc=domain,dc=com
+cn: Karl Cope
+sn: Cope
+givenname: Karl
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: kcope
+mail: kcope@domain.com
+telephonenumber: +1 408 555 2709
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 3040
+userpassword: forfeiture
+
+dn: uid=abarnes,ou=People,dc=domain,dc=com
+cn: Anne-Louise Barnes
+sn: Barnes
+givenname: Anne-Louise
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: abarnes
+mail: abarnes@domain.com
+telephonenumber: +1 408 555 9445
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2290
+userpassword: chevron
+
+dn: uid=rjensen,ou=People,dc=domain,dc=com
+cn: Richard Jensen
+sn: Jensen
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: rjensen
+mail: rjensen@domain.com
+telephonenumber: +1 408 555 5957
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2631
+userpassword: disciplinarian
+
+dn: uid=phun2,ou=People,dc=domain,dc=com
+cn: Pete Hunt
+sn: Hunt
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: phun2
+mail: phun2@domain.com
+telephonenumber: +1 408 555 0342
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0087
+userpassword: absorb
+
+dn: uid=mvaughan,ou=People,dc=domain,dc=com
+cn: Matthew Vaughan
+sn: Vaughan
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: mvaughan
+mail: mvaughan@domain.com
+telephonenumber: +1 408 555 4692
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4508
+userpassword: submitted
+
+dn: uid=jlut2,ou=People,dc=domain,dc=com
+cn: James Lutz
+sn: Lutz
+givenname: James
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jlut2
+mail: jlut2@domain.com
+telephonenumber: +1 408 555 9689
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 3541
+userpassword: shrank
+
+dn: uid=mjablons,ou=People,dc=domain,dc=com
+cn: Morgan Jablonski
+sn: Jablonski
+givenname: Morgan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mjablons
+mail: mjablons@domain.com
+telephonenumber: +1 408 555 0813
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3160
+userpassword: minimal
+
+dn: uid=pchassin,ou=People,dc=domain,dc=com
+cn: Peter Chassin
+sn: Chassin
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: pchassin
+mail: pchassin@domain.com
+telephonenumber: +1 408 555 2816
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 4524
+userpassword: barbital
+
+dn: uid=dcope,ou=People,dc=domain,dc=com
+cn: Dan Cope
+sn: Cope
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: dcope
+mail: dcope@domain.com
+telephonenumber: +1 408 555 9813
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1737
+userpassword: snifter
+
+dn: uid=jrent2,ou=People,dc=domain,dc=com
+cn: Judy Rentz
+sn: Rentz
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jrent2
+mail: jrent2@domain.com
+telephonenumber: +1 408 555 2523
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4405
+userpassword: tachistoscope
+
+dn: uid=tcruse,ou=People,dc=domain,dc=com
+cn: Tobias Cruse
+sn: Cruse
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tcruse
+mail: tcruse@domain.com
+telephonenumber: +1 408 555 5980
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4191
+userpassword: flinty
+
+dn: uid=eward,ou=People,dc=domain,dc=com
+cn: Eric Ward
+sn: Ward
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: eward
+mail: eward@domain.com
+telephonenumber: +1 408 555 2320
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 4874
+userpassword: episcopal
+
+dn: uid=ttully,ou=People,dc=domain,dc=com
+cn: Torrey Tully
+sn: Tully
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: ttully
+mail: ttully@domain.com
+telephonenumber: +1 408 555 2274
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3924
+userpassword: schooner
+
+dn: uid=charvey,ou=People,dc=domain,dc=com
+cn: Cecil Harvey
+sn: Harvey
+givenname: Cecil
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: charvey
+mail: charvey@domain.com
+telephonenumber: +1 408 555 1815
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4583
+userpassword: journalese
+
+dn: uid=rfisher,ou=People,dc=domain,dc=com
+cn: Randy Fisher
+sn: Fisher
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: rfisher
+mail: rfisher@domain.com
+telephonenumber: +1 408 555 1506
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1579
+userpassword: pomegranate
+
+dn: uid=alangdon,ou=People,dc=domain,dc=com
+cn: Andrew Langdon
+sn: Langdon
+givenname: Andrew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: alangdon
+mail: alangdon@domain.com
+telephonenumber: +1 408 555 8289
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 2254
+userpassword: muzzle
+
+dn: uid=drose,ou=People,dc=domain,dc=com
+cn: David Rose
+sn: Rose
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: drose
+mail: drose@domain.com
+telephonenumber: +1 408 555 3963
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4012
+userpassword: gubernatorial
+
+dn: uid=polfield,ou=People,dc=domain,dc=com
+cn: Peter Olfield
+sn: Olfield
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: polfield
+mail: polfield@domain.com
+telephonenumber: +1 408 555 8231
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1376
+userpassword: monologue
+
+dn: uid=awalker,ou=People,dc=domain,dc=com
+cn: Andy Walker
+sn: Walker
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: awalker
+mail: awalker@domain.com
+telephonenumber: +1 408 555 9199
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0061
+userpassword: detonable
+
+dn: uid=lrentz,ou=People,dc=domain,dc=com
+cn: Lex Rentz
+sn: Rentz
+givenname: Lex
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: lrentz
+mail: lrentz@domain.com
+telephonenumber: +1 408 555 2019
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2203
+userpassword: calcium
+
+dn: uid=jvaughan,ou=People,dc=domain,dc=com
+cn: Jeff Vaughan
+sn: Vaughan
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jvaughan
+mail: jvaughan@domain.com
+telephonenumber: +1 408 555 4543
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1734
+userpassword: appoint
+
+dn: uid=bfrancis,ou=People,dc=domain,dc=com
+cn: Barbara Francis
+sn: Francis
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: bfrancis
+mail: bfrancis@domain.com
+telephonenumber: +1 408 555 9111
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3743
+userpassword: holystone
+
+dn: uid=ewalker,ou=People,dc=domain,dc=com
+cn: Eric Walker
+sn: Walker
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Cupertino
+uid: ewalker
+mail: ewalker@domain.com
+telephonenumber: +1 408 555 6387
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 2295
+userpassword: beguile
+
+dn: uid=tjames,ou=People,dc=domain,dc=com
+cn: Tobias James
+sn: James
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tjames
+mail: tjames@domain.com
+telephonenumber: +1 408 555 2458
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 0730
+userpassword: turtle
+
+dn: uid=brigden,ou=People,dc=domain,dc=com
+cn: Bjorn Rigden
+sn: Rigden
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: brigden
+mail: brigden@domain.com
+telephonenumber: +1 408 555 5263
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1643
+userpassword: purple
+
+dn: uid=ecruse,ou=People,dc=domain,dc=com
+cn: Eric Cruse
+sn: Cruse
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: ecruse
+mail: ecruse@domain.com
+telephonenumber: +1 408 555 0648
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4233
+userpassword: platelet
+
+dn: uid=rjense2,ou=People,dc=domain,dc=com
+cn: Randy Jensen
+sn: Jensen
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: rjense2
+mail: rjense2@domain.com
+telephonenumber: +1 408 555 9045
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1984
+userpassword: transpose
+
+dn: uid=rhunt,ou=People,dc=domain,dc=com
+cn: Richard Hunt
+sn: Hunt
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rhunt
+mail: rhunt@domain.com
+telephonenumber: +1 408 555 0139
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 0718
+userpassword: becloud
+
+dn: uid=bparker,ou=People,dc=domain,dc=com
+cn: Barry Parker
+sn: Parker
+givenname: Barry
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: bparker
+mail: bparker@domain.com
+telephonenumber: +1 408 555 4647
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1148
+userpassword: lenticular
+
+dn: uid=ealexand,ou=People,dc=domain,dc=com
+cn: Erin Alexander
+sn: Alexander
+givenname: Erin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: ealexand
+mail: ealexand@domain.com
+telephonenumber: +1 408 555 5563
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 2434
+userpassword: galactose
+
+dn: uid=mtyler,ou=People,dc=domain,dc=com
+cn: Matthew Tyler
+sn: Tyler
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: mtyler
+mail: mtyler@domain.com
+telephonenumber: +1 408 555 7907
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2701
+userpassword: instantiate
+
+dn: uid=elott,ou=People,dc=domain,dc=com
+cn: Emanuel Lott
+sn: Lott
+givenname: Emanuel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: elott
+mail: elott@domain.com
+telephonenumber: +1 408 555 0932
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3906
+userpassword: holdout
+
+dn: uid=cnewport,ou=People,dc=domain,dc=com
+cn: Christoph Newport
+sn: Newport
+givenname: Christoph
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: cnewport
+mail: cnewport@domain.com
+telephonenumber: +1 408 555 0066
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 0056
+userpassword: expertise
+
+dn: uid=jvedder,ou=People,dc=domain,dc=com
+cn: Jeff Vedder
+sn: Vedder
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: jvedder
+mail: jvedder@domain.com
+telephonenumber: +1 408 555 4668
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3445
+userpassword: befitting
+
+dn: cn=Accounting Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: Accounting Managers
+ou: Groups
+uniquemember: uid=scarter,ou=People,dc=domain,dc=com
+uniquemember: uid=tmorris,ou=People,dc=domain,dc=com
+description: People who can manage accounting entries
+
+dn: cn=HR Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: HR Managers
+ou: Groups
+uniquemember: uid=kvaughan,ou=People,dc=domain,dc=com
+uniquemember: uid=cschmith,ou=People,dc=domain,dc=com
+description: People who can manage HR entries
+
+dn: cn=QA Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: QA Managers
+ou: Groups
+uniquemember: uid=abergin,ou=People,dc=domain,dc=com
+uniquemember: uid=jwalker,ou=People,dc=domain,dc=com
+description: People who can manage QA entries
+
+dn: cn=PD Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: PD Managers
+ou: Groups
+uniquemember: uid=kwinters,ou=People,dc=domain,dc=com
+uniquemember: uid=trigden,ou=People,dc=domain,dc=com
+description: People who can manage engineer entries
+
+dn: ou=Netscape Servers,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: Netscape Servers
+description: Standard branch for Netscape Server registration
+

Added: incubator/directory/eve/branches/start/src/ldif/ori_example.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/ori_example.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,2786 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# dc=example,dc=com sample LDIF file
+#
+# Notes:
+#   158 total entries.
+#     - (objectclass=domain) entry (dc=example,dc=com). (Automatically created for suffix)
+#     3 (objectclass=organizationalunit) entries.
+#     5 (objectclass=groupofuniquenames) entries.
+#   150 (objectclass=person) entries (all under	ou=people,dc=example,dc=com).
+#   
+
+dn: ou=Groups, dc=example,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: cn=Directory Administrators, ou=Groups, dc=example,dc=com
+cn: Directory Administrators
+objectclass: top
+objectclass: groupofuniquenames
+ou: Groups
+uniquemember: uid=kvaughan, ou=People, dc=example,dc=com
+uniquemember: uid=rdaugherty, ou=People, dc=example,dc=com
+uniquemember: uid=hmiller, ou=People, dc=example,dc=com
+
+dn: ou=People, dc=example,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: People
+
+dn: ou=Special Users,dc=example,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: Special Users
+description: Special Administrative Accounts
+
+dn: uid=scarter, ou=People, dc=example,dc=com
+cn: Sam Carter
+sn: Carter
+givenname: Sam
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: scarter
+mail: scarter@example.com
+telephonenumber: +1 408 555 4798
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4612
+userpassword: sprain
+
+dn: uid=tmorris, ou=People, dc=example,dc=com
+cn: Ted Morris
+sn: Morris
+givenname: Ted
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tmorris
+mail: tmorris@example.com
+telephonenumber: +1 408 555 9187
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4117
+userpassword: irrefutable
+
+dn: uid=kvaughan, ou=People, dc=example,dc=com
+cn: Kirsten Vaughan
+sn: Vaughan
+givenname: Kirsten
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: kvaughan
+mail: kvaughan@example.com
+telephonenumber: +1 408 555 5625
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 2871
+userpassword: bribery
+# Kirsten is a Directory Administrator and therefore should not
+# be subject to any resource limits.
+
+dn: uid=abergin, ou=People, dc=example,dc=com
+cn: Andy Bergin
+sn: Bergin
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: abergin
+mail: abergin@example.com
+telephonenumber: +1 408 555 8585
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3472
+userpassword: inflict
+
+dn: uid=dmiller, ou=People, dc=example,dc=com
+cn: David Miller
+sn: Miller
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: dmiller
+mail: dmiller@example.com
+telephonenumber: +1 408 555 9423
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4135
+userpassword: gosling
+
+dn: uid=gfarmer, ou=People, dc=example,dc=com
+cn: Gern Farmer
+sn: Farmer
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: gfarmer
+mail: gfarmer@example.com
+telephonenumber: +1 408 555 6201
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1269
+userpassword: ruling
+
+dn: uid=kwinters, ou=People, dc=example,dc=com
+cn: Kelly Winters
+sn: Winters
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: kwinters
+mail: kwinters@example.com
+telephonenumber: +1 408 555 9069
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4178
+userpassword: forsook
+
+dn: uid=trigden, ou=People, dc=example,dc=com
+cn: Torrey Rigden
+sn: Rigden
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: trigden
+mail: trigden@example.com
+telephonenumber: +1 408 555 9280
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3584
+userpassword: sensitive
+
+dn: uid=cschmith, ou=People, dc=example,dc=com
+cn: Chris Schmith
+sn: Schmith
+givenname: Chris
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: cschmith
+mail: cschmith@example.com
+telephonenumber: +1 408 555 8011
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0416
+userpassword: hypotenuse
+
+
+dn: uid=jwallace, ou=People, dc=example,dc=com
+cn: Judy Wallace
+sn: Wallace
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: jwallace
+mail: jwallace@example.com
+telephonenumber: +1 408 555 0319
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1033
+userpassword: linear
+
+dn: uid=jwalker, ou=People, dc=example,dc=com
+cn: John Walker
+sn: Walker
+givenname: John
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: jwalker
+mail: jwalker@example.com
+telephonenumber: +1 408 555 1476
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3915
+userpassword: dogleg
+
+dn: uid=tclow, ou=People, dc=example,dc=com
+cn: Torrey Clow
+sn: Clow
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: tclow
+mail: tclow@example.com
+telephonenumber: +1 408 555 8825
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4376
+userpassword: cardreader
+
+dn: uid=rdaugherty, ou=People, dc=example,dc=com
+cn: Robert Daugherty
+sn: Daugherty
+givenname: Robert
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: rdaugherty
+mail: rdaugherty@example.com
+telephonenumber: +1 408 555 1296
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0194
+userpassword: apples
+# Robert is a Directory Administrator and therefore should not
+# be subject to any resource limits.
+
+dn: uid=jreuter, ou=People, dc=example,dc=com
+cn: Jayne Reuter
+sn: Reuter
+givenname: Jayne
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: jreuter
+mail: jreuter@example.com
+telephonenumber: +1 408 555 1122
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 2942
+userpassword: destroy
+
+dn: uid=tmason, ou=People, dc=example,dc=com
+cn: Torrey Mason
+sn: Mason
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: tmason
+mail: tmason@example.com
+telephonenumber: +1 408 555 1596
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1124
+userpassword: squatted
+
+dn: uid=bhall, ou=People, dc=example,dc=com
+cn: Benjamin Hall
+sn: Hall
+givenname: Benjamin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: bhall
+mail: bhall@example.com
+telephonenumber: +1 408 555 6067
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 2511
+userpassword: oranges
+
+dn: uid=btalbot, ou=People, dc=example,dc=com
+cn: Brad Talbot
+sn: Talbot
+givenname: Brad
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: btalbot
+mail: btalbot@example.com
+telephonenumber: +1 408 555 4992
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3532
+userpassword: trident
+
+dn: uid=mward, ou=People, dc=example,dc=com
+cn: Marcus Ward
+sn: Ward
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: mward
+mail: mward@example.com
+telephonenumber: +1 408 555 5688
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 1707
+userpassword: normal
+
+dn: uid=bjablons, ou=People, dc=example,dc=com
+cn: Barbara Jablonski
+sn: Jablonski
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: bjablons
+mail: bjablons@example.com
+telephonenumber: +1 408 555 8815
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0906
+userpassword: strawberry
+
+dn: uid=jmcFarla, ou=People, dc=example,dc=com
+cn: Judy McFarland
+sn: McFarland
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: jmcFarla
+mail: jmcFarla@example.com
+telephonenumber: +1 408 555 2567
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 2359
+userpassword: walnut
+
+dn: uid=llabonte, ou=People, dc=example,dc=com
+cn: Lee Labonte
+sn: Labonte
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: llabonte
+mail: llabonte@example.com
+telephonenumber: +1 408 555 0957
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2854
+userpassword: sourdough
+
+dn: uid=jcampaig, ou=People, dc=example,dc=com
+cn: Jody Campaigne
+sn: Campaigne
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jcampaig
+mail: jcampaig@example.com
+telephonenumber: +1 408 555 1660
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4385
+userpassword: grapevine
+
+dn: uid=bhal2, ou=People, dc=example,dc=com
+cn: Barbara Hall
+sn: Hall
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: bhal2
+mail: bhal2@example.com
+telephonenumber: +1 408 555 4491
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2758
+userpassword: truths
+
+dn: uid=alutz, ou=People, dc=example,dc=com
+cn: Alexander Lutz
+sn: Lutz
+givenname: Alexander
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: alutz
+mail: alutz@example.com
+telephonenumber: +1 408 555 6505
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 1327
+userpassword: northward
+
+dn: uid=btalbo2, ou=People, dc=example,dc=com
+cn: Bjorn Talbot
+sn: Talbot
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: btalbo2
+mail: btalbo2@example.com
+telephonenumber: +1 408 555 4234
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1205
+userpassword: corduroy
+
+dn: uid=achassin, ou=People, dc=example,dc=com
+cn: Ashley Chassin
+sn: Chassin
+givenname: Ashley
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: achassin
+mail: achassin@example.com
+telephonenumber: +1 408 555 9972
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0466
+userpassword: duopolist
+
+dn: uid=hmiller, ou=People, dc=example,dc=com
+cn: Harry Miller
+sn: Miller
+givenname: Harry
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: hmiller
+mail: hmiller@example.com
+telephonenumber: +1 408 555 9804
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4304
+userpassword: hillock
+# Harry is a Directory Administrator and therefore should not
+# be subject to any resource limits.
+
+dn: uid=jcampai2, ou=People, dc=example,dc=com
+cn: Jeffrey Campaigne
+sn: Campaigne
+givenname: Jeffrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jcampai2
+mail: jcampai2@example.com
+telephonenumber: +1 408 555 7393
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 1377
+userpassword: nominee
+
+dn: uid=lulrich, ou=People, dc=example,dc=com
+cn: Lee Ulrich
+sn: Ulrich
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: lulrich
+mail: lulrich@example.com
+telephonenumber: +1 408 555 8652
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 0985
+userpassword: attribution
+
+dn: uid=mlangdon, ou=People, dc=example,dc=com
+cn: Marcus Langdon
+sn: Langdon
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: mlangdon
+mail: mlangdon@example.com
+telephonenumber: +1 408 555 6249
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4471
+userpassword: threat
+
+dn: uid=striplet, ou=People, dc=example,dc=com
+cn: Stephen Triplett
+sn: Triplett
+givenname: Stephen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: striplet
+mail: striplet@example.com
+telephonenumber: +1 408 555 4519
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3083
+userpassword: compactify
+
+dn: uid=gtriplet, ou=People, dc=example,dc=com
+cn: Gern Triplett
+sn: Triplett
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: gtriplet
+mail: gtriplet@example.com
+telephonenumber: +1 408 555 2582
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 4023
+userpassword: placeable
+
+dn: uid=jfalena, ou=People, dc=example,dc=com
+cn: John Falena
+sn: Falena
+givenname: John
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jfalena
+mail: jfalena@example.com
+telephonenumber: +1 408 555 8133
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1917
+userpassword: nightly
+
+dn: uid=speterso, ou=People, dc=example,dc=com
+cn: Sue Peterson
+sn: Peterson
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: speterso
+mail: speterso@example.com
+telephonenumber: +1 408 555 3613
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 3073
+userpassword: quinine
+
+dn: uid=ejohnson, ou=People, dc=example,dc=com
+cn: Emanuel Johnson
+sn: Johnson
+givenname: Emanuel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ejohnson
+mail: ejohnson@example.com
+telephonenumber: +1 408 555 3287
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 3737
+userpassword: marketwise
+
+dn: uid=prigden, ou=People, dc=example,dc=com
+cn: Peter Rigden
+sn: Rigden
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: prigden
+mail: prigden@example.com
+telephonenumber: +1 408 555 5099
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1271
+userpassword: epiphyseal
+
+dn: uid=bwalker, ou=People, dc=example,dc=com
+cn: Brad Walker
+sn: Walker
+givenname: Brad
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bwalker
+mail: bwalker@example.com
+telephonenumber: +1 408 555 5476
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3529
+userpassword: interruptible
+
+dn: uid=kjensen, ou=People, dc=example,dc=com
+cn: Kurt Jensen
+sn: Jensen
+givenname: Kurt
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: kjensen
+mail: kjensen@example.com
+telephonenumber: +1 408 555 6127
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1944
+userpassword: regulatory
+
+dn: uid=mlott, ou=People, dc=example,dc=com
+cn: Mike Lott
+sn: Lott
+givenname: Mike
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: mlott
+mail: mlott@example.com
+telephonenumber: +1 408 555 2234
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 0498
+userpassword: cognac
+
+dn: uid=cwallace, ou=People, dc=example,dc=com
+cn: Cecil Wallace
+sn: Wallace
+givenname: Cecil
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: cwallace
+mail: cwallace@example.com
+telephonenumber: +1 408 555 6438
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0349
+userpassword: quintus
+
+dn: uid=tpierce, ou=People, dc=example,dc=com
+cn: Tobias Pierce
+sn: Pierce
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tpierce
+mail: tpierce@example.com
+telephonenumber: +1 408 555 1531
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1383
+userpassword: rascal
+
+dn: uid=rbannist, ou=People, dc=example,dc=com
+cn: Richard Bannister
+sn: Bannister
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rbannist
+mail: rbannist@example.com
+telephonenumber: +1 408 555 1833
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0983
+userpassword: demonstrate
+
+dn: uid=bplante, ou=People, dc=example,dc=com
+cn: Brian Plante
+sn: Plante
+givenname: Brian
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: bplante
+mail: bplante@example.com
+telephonenumber: +1 408 555 3550
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4654
+userpassword: tangerine
+
+dn: uid=rmills, ou=People, dc=example,dc=com
+cn: Randy Mills
+sn: Mills
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rmills
+mail: rmills@example.com
+telephonenumber: +1 408 555 2072
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 3823
+userpassword: condescend
+
+dn: uid=bschneid, ou=People, dc=example,dc=com
+cn: Benjamin Schneider
+sn: Schneider
+givenname: Benjamin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: bschneid
+mail: bschneid@example.com
+telephonenumber: +1 408 555 1012
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 4471
+userpassword: biblical
+
+dn: uid=skellehe, ou=People, dc=example,dc=com
+cn: Sue Kelleher
+sn: Kelleher
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: skellehe
+mail: skellehe@example.com
+telephonenumber: +1 408 555 3480
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1608
+userpassword: sweltering
+
+dn: uid=brentz, ou=People, dc=example,dc=com
+cn: Bertram Rentz
+sn: Rentz
+givenname: Bertram
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: brentz
+mail: brentz@example.com
+telephonenumber: +1 408 555 5526
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0617
+userpassword: diachronic
+
+dn: uid=dsmith, ou=People, dc=example,dc=com
+cn: Daniel Smith
+sn: Smith
+givenname: Daniel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: dsmith
+mail: dsmith@example.com
+telephonenumber: +1 408 555 9519
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0368
+userpassword: quantitative
+
+dn: uid=scarte2, ou=People, dc=example,dc=com
+cn: Stephen Carter
+sn: Carter
+givenname: Stephen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: scarte2
+mail: scarte2@example.com
+telephonenumber: +1 408 555 6022
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 2013
+userpassword: scooter
+
+dn: uid=dthorud, ou=People, dc=example,dc=com
+cn: David Thorud
+sn: Thorud
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: dthorud
+mail: dthorud@example.com
+telephonenumber: +1 408 555 6185
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1128
+userpassword: fulcrum
+
+dn: uid=ekohler, ou=People, dc=example,dc=com
+cn: Elba Kohler
+sn: Kohler
+givenname: Elba
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: ekohler
+mail: ekohler@example.com
+telephonenumber: +1 408 555 1926
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 2721
+userpassword: guildhall
+
+dn: uid=lcampbel, ou=People, dc=example,dc=com
+cn: Laurel Campbell
+sn: Campbell
+givenname: Laurel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: lcampbel
+mail: lcampbel@example.com
+telephonenumber: +1 408 555 2537
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 2073
+userpassword: impress
+
+dn: uid=tlabonte, ou=People, dc=example,dc=com
+cn: Tim Labonte
+sn: Labonte
+givenname: Tim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tlabonte
+mail: tlabonte@example.com
+telephonenumber: +1 408 555 0058
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1426
+userpassword: express
+
+dn: uid=slee, ou=People, dc=example,dc=com
+cn: Scott Lee
+sn: Lee
+givenname: Scott
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: slee
+mail: slee@example.com
+telephonenumber: +1 408 555 2335
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 1806
+userpassword: revertive
+
+dn: uid=bfree, ou=People, dc=example,dc=com
+cn: Bjorn Free
+sn: Free
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: bfree
+mail: bfree@example.com
+telephonenumber: +1 408 555 8588
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3307
+userpassword: etiquette
+
+dn: uid=tschneid, ou=People, dc=example,dc=com
+cn: Torrey Schneider
+sn: Schneider
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tschneid
+mail: tschneid@example.com
+telephonenumber: +1 408 555 7086
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2292
+userpassword: chaperone
+
+dn: uid=prose, ou=People, dc=example,dc=com
+cn: Paula Rose
+sn: Rose
+givenname: Paula
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: prose
+mail: prose@example.com
+telephonenumber: +1 408 555 9998
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 0542
+userpassword: regatta
+
+dn: uid=jhunter, ou=People, dc=example,dc=com
+cn: Janet Hunter
+sn: Hunter
+givenname: Janet
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: jhunter
+mail: jhunter@example.com
+telephonenumber: +1 408 555 7665
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4856
+userpassword: nanometer
+
+dn: uid=ashelton, ou=People, dc=example,dc=com
+cn: Alexander Shelton
+sn: Shelton
+givenname: Alexander
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: ashelton
+mail: ashelton@example.com
+telephonenumber: +1 408 555 1081
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1987
+userpassword: appointe
+
+dn: uid=mmcinnis, ou=People, dc=example,dc=com
+cn: Marcus Mcinnis
+sn: Mcinnis
+givenname: Marcus
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: mmcinnis
+mail: mmcinnis@example.com
+telephonenumber: +1 408 555 9655
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4818
+userpassword: calcify
+
+dn: uid=falbers, ou=People, dc=example,dc=com
+cn: Frank Albers
+sn: Albers
+givenname: Frank
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: falbers
+mail: falbers@example.com
+telephonenumber: +1 408 555 3094
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1439
+userpassword: degradation
+
+dn: uid=mschneid, ou=People, dc=example,dc=com
+cn: Martin Schneider
+sn: Schneider
+givenname: Martin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mschneid
+mail: mschneid@example.com
+telephonenumber: +1 408 555 5017
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 3153
+userpassword: motorcycle
+
+dn: uid=pcruse, ou=People, dc=example,dc=com
+cn: Patricia Cruse
+sn: Cruse
+givenname: Patricia
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: pcruse
+mail: pcruse@example.com
+telephonenumber: +1 408 555 8641
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3967
+userpassword: pauper
+
+dn: uid=tkelly, ou=People, dc=example,dc=com
+cn: Timothy Kelly
+sn: Kelly
+givenname: Timothy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+l: Santa Clara
+uid: tkelly
+mail: tkelly@example.com
+telephonenumber: +1 408 555 4295
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3107
+userpassword: risible
+
+dn: uid=ahel, ou=People, dc=example,dc=com
+cn: Andrew Hel
+sn: Hel
+givenname: Andrew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ahel
+mail: ahel@example.com
+telephonenumber: +1 408 555 2666
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0572
+userpassword: sarsaparilla
+
+dn: uid=jburrell, ou=People, dc=example,dc=com
+cn: James Burrell
+sn: Burrell
+givenname: James
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jburrell
+mail: jburrell@example.com
+telephonenumber: +1 408 555 0751
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4926
+userpassword: degrease
+
+dn: uid=smason, ou=People, dc=example,dc=com
+cn: Sue Mason
+sn: Mason
+givenname: Sue
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: smason
+mail: smason@example.com
+telephonenumber: +1 408 555 9780
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4971
+userpassword: sensible
+
+dn: uid=ptyler, ou=People, dc=example,dc=com
+cn: Pete Tyler
+sn: Tyler
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ptyler
+mail: ptyler@example.com
+telephonenumber: +1 408 555 3335
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0327
+userpassword: vinegar
+
+dn: uid=calexand, ou=People, dc=example,dc=com
+cn: Chris Alexander
+sn: Alexander
+givenname: Chris
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: calexand
+mail: calexand@example.com
+telephonenumber: +1 408 555 9438
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2884
+userpassword: dauphin
+
+dn: uid=jcruse, ou=People, dc=example,dc=com
+cn: Jim Cruse
+sn: Cruse
+givenname: Jim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jcruse
+mail: jcruse@example.com
+telephonenumber: +1 408 555 9482
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 0083
+userpassword: bridgework
+
+dn: uid=kcarter, ou=People, dc=example,dc=com
+cn: Karen Carter
+sn: Carter
+givenname: Karen
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: kcarter
+mail: kcarter@example.com
+telephonenumber: +1 408 555 4675
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 2320
+userpassword: radiosonde
+
+dn: uid=rfish, ou=People, dc=example,dc=com
+cn: Randy Fish
+sn: Fish
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rfish
+mail: rfish@example.com
+telephonenumber: +1 408 555 9865
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2317
+userpassword: mailbox
+
+dn: uid=phunt, ou=People, dc=example,dc=com
+cn: Philip Hunt
+sn: Hunt
+givenname: Philip
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: phunt
+mail: phunt@example.com
+telephonenumber: +1 408 555 1242
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 1183
+userpassword: wastewater
+
+dn: uid=rschneid, ou=People, dc=example,dc=com
+cn: Rachel Schneider
+sn: Schneider
+givenname: Rachel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: rschneid
+mail: rschneid@example.com
+telephonenumber: +1 408 555 9908
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4183
+userpassword: decorous
+
+dn: uid=bjensen, ou=People, dc=example,dc=com
+cn: Barbara Jensen
+cn: Babs Jensen
+sn: Jensen
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: bjensen
+mail: bjensen@example.com
+telephonenumber: +1 408 555 1862
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 0209
+userpassword: hifalutin
+
+dn: uid=jlange, ou=People, dc=example,dc=com
+cn: Jim Lange
+sn: Lange
+givenname: Jim
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: jlange
+mail: jlange@example.com
+telephonenumber: +1 408 555 0488
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3798
+userpassword: chastity
+
+dn: uid=rulrich, ou=People, dc=example,dc=com
+cn: Randy Ulrich
+sn: Ulrich
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: rulrich
+mail: rulrich@example.com
+telephonenumber: +1 408 555 5311
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1282
+userpassword: twinkle
+
+dn: uid=rfrancis, ou=People, dc=example,dc=com
+cn: Richard Francis
+sn: Francis
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rfrancis
+mail: rfrancis@example.com
+telephonenumber: +1 408 555 8157
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3482
+userpassword: hacienda
+
+dn: uid=mwhite, ou=People, dc=example,dc=com
+cn: Morgan White
+sn: White
+givenname: Morgan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mwhite
+mail: mwhite@example.com
+telephonenumber: +1 408 555 9620
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3088
+userpassword: staple
+
+dn: uid=gjensen, ou=People, dc=example,dc=com
+cn: Gern Jensen
+sn: Jensen
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: gjensen
+mail: gjensen@example.com
+telephonenumber: +1 408 555 3299
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4609
+userpassword: primitive
+
+dn: uid=awhite, ou=People, dc=example,dc=com
+cn: Alan White
+sn: White
+givenname: Alan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: awhite
+mail: awhite@example.com
+telephonenumber: +1 408 555 3232
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 0142
+userpassword: placeholder
+
+dn: uid=bmaddox, ou=People, dc=example,dc=com
+cn: Barbara Maddox
+sn: Maddox
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bmaddox
+mail: bmaddox@example.com
+telephonenumber: +1 408 555 7783
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 2207
+userpassword: feedback
+
+dn: uid=mtalbot, ou=People, dc=example,dc=com
+cn: Martin Talbot
+sn: Talbot
+givenname: Martin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: mtalbot
+mail: mtalbot@example.com
+telephonenumber: +1 408 555 9228
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1415
+userpassword: currant
+
+dn: uid=jbrown, ou=People, dc=example,dc=com
+cn: Judy Brown
+sn: Brown
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jbrown
+mail: jbrown@example.com
+telephonenumber: +1 408 555 6885
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4224
+userpassword: militiamen
+
+dn: uid=jjensen, ou=People, dc=example,dc=com
+cn: Jody Jensen
+sn: Jensen
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: jjensen
+mail: jjensen@example.com
+telephonenumber: +1 408 555 7587
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4882
+userpassword: borderland
+
+dn: uid=mcarter, ou=People, dc=example,dc=com
+cn: Mike Carter
+sn: Carter
+givenname: Mike
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: mcarter
+mail: mcarter@example.com
+telephonenumber: +1 408 555 1846
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3819
+userpassword: mainland
+
+dn: uid=dakers, ou=People, dc=example,dc=com
+cn: David Akers
+sn: Akers
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: dakers
+mail: dakers@example.com
+telephonenumber: +1 408 555 4812
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 4944
+userpassword: integument
+
+dn: uid=sfarmer, ou=People, dc=example,dc=com
+cn: Scott Farmer
+sn: Farmer
+givenname: Scott
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: sfarmer
+mail: sfarmer@example.com
+telephonenumber: +1 408 555 4228
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0019
+userpassword: triumphal
+
+dn: uid=dward, ou=People, dc=example,dc=com
+cn: Daniel Ward
+sn: Ward
+givenname: Daniel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: dward
+mail: dward@example.com
+telephonenumber: +1 408 555 5322
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3927
+userpassword: armload
+
+dn: uid=tward, ou=People, dc=example,dc=com
+cn: Tobias Ward
+sn: Ward
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: tward
+mail: tward@example.com
+telephonenumber: +1 408 555 7202
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2238
+userpassword: cedilla
+
+dn: uid=pshelton, ou=People, dc=example,dc=com
+cn: Patricia Shelton
+sn: Shelton
+givenname: Patricia
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Cupertino
+uid: pshelton
+mail: pshelton@example.com
+telephonenumber: +1 408 555 6442
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2918
+userpassword: nosedive
+
+dn: uid=jrentz, ou=People, dc=example,dc=com
+cn: Jody Rentz
+sn: Rentz
+givenname: Jody
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jrentz
+mail: jrentz@example.com
+telephonenumber: +1 408 555 5829
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3025
+userpassword: meander
+
+dn: uid=plorig, ou=People, dc=example,dc=com
+cn: Peter Lorig
+sn: Lorig
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: plorig
+mail: plorig@example.com
+telephonenumber: +1 408 555 0624
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1276
+userpassword: calorimeter
+
+dn: uid=ajensen, ou=People, dc=example,dc=com
+cn: Allison Jensen
+sn: Jensen
+givenname: Allison
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: ajensen
+mail: ajensen@example.com
+telephonenumber: +1 408 555 7892
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 0784
+userpassword: coltsfoot
+
+dn: uid=kschmith, ou=People, dc=example,dc=com
+cn: Kelly Schmith
+sn: Schmith
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: kschmith
+mail: kschmith@example.com
+telephonenumber: +1 408 555 9749
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 2221
+userpassword: purvey
+
+dn: uid=pworrell, ou=People, dc=example,dc=com
+cn: Pete Worrell
+sn: Worrell
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: pworrell
+mail: pworrell@example.com
+telephonenumber: +1 408 555 1637
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 2449
+userpassword: solicitous
+
+dn: uid=mreuter, ou=People, dc=example,dc=com
+cn: Matthew Reuter
+sn: Reuter
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: mreuter
+mail: mreuter@example.com
+telephonenumber: +1 408 555 6879
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 1356
+userpassword: oblivious
+
+dn: uid=gtyler, ou=People, dc=example,dc=com
+cn: Gern Tyler
+sn: Tyler
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: gtyler
+mail: gtyler@example.com
+telephonenumber: +1 408 555 1020
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0312
+userpassword: typology
+
+dn: uid=tschmith, ou=People, dc=example,dc=com
+cn: Tobias Schmith
+sn: Schmith
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tschmith
+mail: tschmith@example.com
+telephonenumber: +1 408 555 9626
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4607
+userpassword: compost
+
+dn: uid=bjense2, ou=People, dc=example,dc=com
+cn: Bjorn Jensen
+sn: Jensen
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: bjense2
+mail: bjense2@example.com
+telephonenumber: +1 408 555 5655
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4294
+userpassword: mortgage
+
+dn: uid=dswain, ou=People, dc=example,dc=com
+cn: Dietrich Swain
+sn: Swain
+givenname: Dietrich
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Sunnyvale
+uid: dswain
+mail: dswain@example.com
+telephonenumber: +1 408 555 9222
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4396
+userpassword: freedom
+
+dn: uid=ahall, ou=People, dc=example,dc=com
+cn: Andy Hall
+sn: Hall
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: ahall
+mail: ahall@example.com
+telephonenumber: +1 408 555 6169
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 3050
+userpassword: slater
+
+dn: uid=jmuffly, ou=People, dc=example,dc=com
+cn: Jeff Muffly
+sn: Muffly
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jmuffly
+mail: jmuffly@example.com
+telephonenumber: +1 408 555 5287
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 0997
+userpassword: dictate
+
+dn: uid=tjensen, ou=People, dc=example,dc=com
+cn: Ted Jensen
+sn: Jensen
+givenname: Ted
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tjensen
+mail: tjensen@example.com
+telephonenumber: +1 408 555 8622
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4717
+userpassword: ecosystem
+
+dn: uid=ahunter, ou=People, dc=example,dc=com
+cn: Allison Hunter
+sn: Hunter
+givenname: Allison
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Sunnyvale
+uid: ahunter
+mail: ahunter@example.com
+telephonenumber: +1 408 555 7713
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1213
+userpassword: egregious
+
+dn: uid=jgoldste, ou=People, dc=example,dc=com
+cn: Jon Goldstein
+sn: Goldstein
+givenname: Jon
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jgoldste
+mail: jgoldste@example.com
+telephonenumber: +1 408 555 5769
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 1454
+userpassword: yellow
+
+dn: uid=aworrell, ou=People, dc=example,dc=com
+cn: Alan Worrell
+sn: Worrell
+givenname: Alan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: aworrell
+mail: aworrell@example.com
+telephonenumber: +1 408 555 1591
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 3966
+userpassword: gargoyle
+
+dn: uid=wlutz, ou=People, dc=example,dc=com
+cn: Wendy Lutz
+sn: Lutz
+givenname: Wendy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: wlutz
+mail: wlutz@example.com
+telephonenumber: +1 408 555 3358
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 4912
+userpassword: bassinet
+
+dn: uid=jlutz, ou=People, dc=example,dc=com
+cn: Janet Lutz
+sn: Lutz
+givenname: Janet
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jlutz
+mail: jlutz@example.com
+telephonenumber: +1 408 555 4902
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2544
+userpassword: autumn
+
+dn: uid=dlangdon, ou=People, dc=example,dc=com
+cn: Dan Langdon
+sn: Langdon
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: dlangdon
+mail: dlangdon@example.com
+telephonenumber: +1 408 555 7044
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3263
+userpassword: botulin
+
+dn: uid=aknutson, ou=People, dc=example,dc=com
+cn: Ashley Knutson
+sn: Knutson
+givenname: Ashley
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: aknutson
+mail: aknutson@example.com
+telephonenumber: +1 408 555 2169
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4736
+userpassword: maltose
+
+dn: uid=kmcinnis, ou=People, dc=example,dc=com
+cn: Kelly Mcinnis
+sn: Mcinnis
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: kmcinnis
+mail: kmcinnis@example.com
+telephonenumber: +1 408 555 8596
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4312
+userpassword: stargaze
+
+dn: uid=tcouzens, ou=People, dc=example,dc=com
+cn: Trent Couzens
+sn: Couzens
+givenname: Trent
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: tcouzens
+mail: tcouzens@example.com
+telephonenumber: +1 408 555 8401
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 3994
+userpassword: tambourine
+
+dn: uid=lstockto, ou=People, dc=example,dc=com
+cn: Lee Stockton
+sn: Stockton
+givenname: Lee
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: lstockto
+mail: lstockto@example.com
+telephonenumber: +1 408 555 0518
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0169
+userpassword: brooklyn
+
+dn: uid=jbourke, ou=People, dc=example,dc=com
+cn: Jon Bourke
+sn: Bourke
+givenname: Jon
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Cupertino
+uid: jbourke
+mail: jbourke@example.com
+telephonenumber: +1 408 555 8541
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0034
+userpassword: brainwash
+
+dn: uid=dlanoway, ou=People, dc=example,dc=com
+cn: Dan Lanoway
+sn: Lanoway
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: dlanoway
+mail: dlanoway@example.com
+telephonenumber: +1 408 555 2017
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3540
+userpassword: manhattan
+
+dn: uid=kcope, ou=People, dc=example,dc=com
+cn: Karl Cope
+sn: Cope
+givenname: Karl
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: kcope
+mail: kcope@example.com
+telephonenumber: +1 408 555 2709
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 3040
+userpassword: forfeiture
+
+dn: uid=abarnes, ou=People, dc=example,dc=com
+cn: Anne-Louise Barnes
+sn: Barnes
+givenname: Anne-Louise
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: abarnes
+mail: abarnes@example.com
+telephonenumber: +1 408 555 9445
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2290
+userpassword: chevron
+
+dn: uid=rjensen, ou=People, dc=example,dc=com
+cn: Richard Jensen
+sn: Jensen
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: rjensen
+mail: rjensen@example.com
+telephonenumber: +1 408 555 5957
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 2631
+userpassword: disciplinarian
+
+dn: uid=phun2, ou=People, dc=example,dc=com
+cn: Pete Hunt
+sn: Hunt
+givenname: Pete
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: phun2
+mail: phun2@example.com
+telephonenumber: +1 408 555 0342
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 0087
+userpassword: absorb
+
+dn: uid=mvaughan, ou=People, dc=example,dc=com
+cn: Matthew Vaughan
+sn: Vaughan
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: mvaughan
+mail: mvaughan@example.com
+telephonenumber: +1 408 555 4692
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4508
+userpassword: submitted
+
+dn: uid=jlut2, ou=People, dc=example,dc=com
+cn: James Lutz
+sn: Lutz
+givenname: James
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: jlut2
+mail: jlut2@example.com
+telephonenumber: +1 408 555 9689
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 3541
+userpassword: shrank
+
+dn: uid=mjablons, ou=People, dc=example,dc=com
+cn: Morgan Jablonski
+sn: Jablonski
+givenname: Morgan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: mjablons
+mail: mjablons@example.com
+telephonenumber: +1 408 555 0813
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3160
+userpassword: minimal
+
+dn: uid=pchassin, ou=People, dc=example,dc=com
+cn: Peter Chassin
+sn: Chassin
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: pchassin
+mail: pchassin@example.com
+telephonenumber: +1 408 555 2816
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 4524
+userpassword: barbital
+
+dn: uid=dcope, ou=People, dc=example,dc=com
+cn: Dan Cope
+sn: Cope
+givenname: Dan
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: dcope
+mail: dcope@example.com
+telephonenumber: +1 408 555 9813
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 1737
+userpassword: snifter
+
+dn: uid=jrent2, ou=People, dc=example,dc=com
+cn: Judy Rentz
+sn: Rentz
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Santa Clara
+uid: jrent2
+mail: jrent2@example.com
+telephonenumber: +1 408 555 2523
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4405
+userpassword: tachistoscope
+
+dn: uid=tcruse, ou=People, dc=example,dc=com
+cn: Tobias Cruse
+sn: Cruse
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: tcruse
+mail: tcruse@example.com
+telephonenumber: +1 408 555 5980
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 4191
+userpassword: flinty
+
+dn: uid=eward, ou=People, dc=example,dc=com
+cn: Eric Ward
+sn: Ward
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: eward
+mail: eward@example.com
+telephonenumber: +1 408 555 2320
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 4874
+userpassword: episcopal
+
+dn: uid=ttully, ou=People, dc=example,dc=com
+cn: Torrey Tully
+sn: Tully
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: ttully
+mail: ttully@example.com
+telephonenumber: +1 408 555 2274
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3924
+userpassword: schooner
+
+dn: uid=charvey, ou=People, dc=example,dc=com
+cn: Cecil Harvey
+sn: Harvey
+givenname: Cecil
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: charvey
+mail: charvey@example.com
+telephonenumber: +1 408 555 1815
+facsimiletelephonenumber: +1 408 555 3825
+roomnumber: 4583
+userpassword: journalese
+
+dn: uid=rfisher, ou=People, dc=example,dc=com
+cn: Randy Fisher
+sn: Fisher
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: rfisher
+mail: rfisher@example.com
+telephonenumber: +1 408 555 1506
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1579
+userpassword: pomegranate
+
+dn: uid=alangdon, ou=People, dc=example,dc=com
+cn: Andrew Langdon
+sn: Langdon
+givenname: Andrew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: alangdon
+mail: alangdon@example.com
+telephonenumber: +1 408 555 8289
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 2254
+userpassword: muzzle
+
+dn: uid=drose, ou=People, dc=example,dc=com
+cn: David Rose
+sn: Rose
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: drose
+mail: drose@example.com
+telephonenumber: +1 408 555 3963
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4012
+userpassword: gubernatorial
+
+dn: uid=polfield, ou=People, dc=example,dc=com
+cn: Peter Olfield
+sn: Olfield
+givenname: Peter
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: polfield
+mail: polfield@example.com
+telephonenumber: +1 408 555 8231
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1376
+userpassword: monologue
+
+dn: uid=awalker, ou=People, dc=example,dc=com
+cn: Andy Walker
+sn: Walker
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: awalker
+mail: awalker@example.com
+telephonenumber: +1 408 555 9199
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 0061
+userpassword: detonable
+
+dn: uid=lrentz, ou=People, dc=example,dc=com
+cn: Lex Rentz
+sn: Rentz
+givenname: Lex
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: lrentz
+mail: lrentz@example.com
+telephonenumber: +1 408 555 2019
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 2203
+userpassword: calcium
+
+dn: uid=jvaughan, ou=People, dc=example,dc=com
+cn: Jeff Vaughan
+sn: Vaughan
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: jvaughan
+mail: jvaughan@example.com
+telephonenumber: +1 408 555 4543
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 1734
+userpassword: appoint
+
+dn: uid=bfrancis, ou=People, dc=example,dc=com
+cn: Barbara Francis
+sn: Francis
+givenname: Barbara
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: bfrancis
+mail: bfrancis@example.com
+telephonenumber: +1 408 555 9111
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3743
+userpassword: holystone
+
+dn: uid=ewalker, ou=People, dc=example,dc=com
+cn: Eric Walker
+sn: Walker
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Payroll
+ou: People
+l: Cupertino
+uid: ewalker
+mail: ewalker@example.com
+telephonenumber: +1 408 555 6387
+facsimiletelephonenumber: +1 408 555 8721
+roomnumber: 2295
+userpassword: beguile
+
+dn: uid=tjames, ou=People, dc=example,dc=com
+cn: Tobias James
+sn: James
+givenname: Tobias
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tjames
+mail: tjames@example.com
+telephonenumber: +1 408 555 2458
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 0730
+userpassword: turtle
+
+dn: uid=brigden, ou=People, dc=example,dc=com
+cn: Bjorn Rigden
+sn: Rigden
+givenname: Bjorn
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: brigden
+mail: brigden@example.com
+telephonenumber: +1 408 555 5263
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1643
+userpassword: purple
+
+dn: uid=ecruse, ou=People, dc=example,dc=com
+cn: Eric Cruse
+sn: Cruse
+givenname: Eric
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: ecruse
+mail: ecruse@example.com
+telephonenumber: +1 408 555 0648
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4233
+userpassword: platelet
+
+dn: uid=rjense2, ou=People, dc=example,dc=com
+cn: Randy Jensen
+sn: Jensen
+givenname: Randy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Sunnyvale
+uid: rjense2
+mail: rjense2@example.com
+telephonenumber: +1 408 555 9045
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 1984
+userpassword: transpose
+
+dn: uid=rhunt, ou=People, dc=example,dc=com
+cn: Richard Hunt
+sn: Hunt
+givenname: Richard
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: rhunt
+mail: rhunt@example.com
+telephonenumber: +1 408 555 0139
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 0718
+userpassword: becloud
+
+dn: uid=bparker, ou=People, dc=example,dc=com
+cn: Barry Parker
+sn: Parker
+givenname: Barry
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: bparker
+mail: bparker@example.com
+telephonenumber: +1 408 555 4647
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1148
+userpassword: lenticular
+
+dn: uid=ealexand, ou=People, dc=example,dc=com
+cn: Erin Alexander
+sn: Alexander
+givenname: Erin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: ealexand
+mail: ealexand@example.com
+telephonenumber: +1 408 555 5563
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 2434
+userpassword: galactose
+
+dn: uid=mtyler, ou=People, dc=example,dc=com
+cn: Matthew Tyler
+sn: Tyler
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: mtyler
+mail: mtyler@example.com
+telephonenumber: +1 408 555 7907
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2701
+userpassword: instantiate
+
+dn: uid=elott, ou=People, dc=example,dc=com
+cn: Emanuel Lott
+sn: Lott
+givenname: Emanuel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: elott
+mail: elott@example.com
+telephonenumber: +1 408 555 0932
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3906
+userpassword: holdout
+
+dn: uid=cnewport, ou=People, dc=example,dc=com
+cn: Christoph Newport
+sn: Newport
+givenname: Christoph
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: cnewport
+mail: cnewport@example.com
+telephonenumber: +1 408 555 0066
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 0056
+userpassword: expertise
+
+dn: uid=jvedder, ou=People, dc=example,dc=com
+cn: Jeff Vedder
+sn: Vedder
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: jvedder
+mail: jvedder@example.com
+telephonenumber: +1 408 555 4668
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3445
+userpassword: befitting
+
+dn: cn=Accounting Managers,ou=groups,dc=example,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: Accounting Managers
+ou: groups
+uniquemember: uid=scarter, ou=People, dc=example,dc=com
+uniquemember: uid=tmorris, ou=People, dc=example,dc=com
+description: People who can manage accounting entries
+
+dn: cn=HR Managers,ou=groups,dc=example,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: HR Managers
+ou: groups
+uniquemember: uid=kvaughan, ou=People, dc=example,dc=com
+uniquemember: uid=cschmith, ou=People, dc=example,dc=com
+description: People who can manage HR entries
+
+dn: cn=QA Managers,ou=groups,dc=example,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: QA Managers
+ou: groups
+uniquemember: uid=abergin, ou=People, dc=example,dc=com
+uniquemember: uid=jwalker, ou=People, dc=example,dc=com
+description: People who can manage QA entries
+
+dn: cn=PD Managers,ou=groups,dc=example,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: PD Managers
+ou: groups
+uniquemember: uid=kwinters, ou=People, dc=example,dc=com
+uniquemember: uid=trigden, ou=People, dc=example,dc=com
+description: People who can manage engineer entries
+

Added: incubator/directory/eve/branches/start/src/ldif/smallest_example.ldif
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/ldif/smallest_example.ldif	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,408 @@
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# dc=domain,dc=com sample LDIF file
+#
+# Notes:
+#   160 total entries.
+#     1 (objectclass=domain) entry (dc=domain,dc=com).
+#     4 (objectclass=organizationalunit) entries.
+#     5 (objectclass=groupofuniquenames) entries.
+#   150 (objectclass=person) entries (all under	ou=people,dc=domain,dc=com).
+#   
+
+dn: ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: cn=Directory Administrators,ou=Groups,dc=domain,dc=com
+cn: Directory Administrators
+objectclass: top
+objectclass: groupofuniquenames
+ou: Groups
+uniquemember: uid=kvaughan,ou=People,dc=domain,dc=com
+uniquemember: uid=rdaugherty,ou=People,dc=domain,dc=com
+uniquemember: uid=hmiller,ou=People,dc=domain,dc=com
+
+dn: ou=People,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: People
+
+dn: ou=Special Users,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: Special Users
+description: Special Administrative Accounts
+
+dn: uid=scarter,ou=People,dc=domain,dc=com
+cn: Sam Carter
+sn: Carter
+givenname: Sam
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: scarter
+mail: scarter@domain.com
+telephonenumber: +1 408 555 4798
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 4612
+userpassword: sprain
+
+dn: uid=tmorris,ou=People,dc=domain,dc=com
+cn: Ted Morris
+sn: Morris
+givenname: Ted
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Santa Clara
+uid: tmorris
+mail: tmorris@domain.com
+telephonenumber: +1 408 555 9187
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 4117
+userpassword: irrefutable
+
+dn: uid=kvaughan,ou=People,dc=domain,dc=com
+cn: Kirsten Vaughan
+sn: Vaughan
+givenname: Kirsten
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Sunnyvale
+uid: kvaughan
+mail: kvaughan@domain.com
+telephonenumber: +1 408 555 5625
+facsimiletelephonenumber: +1 408 555 3372
+roomnumber: 2871
+userpassword: bribery
+
+dn: uid=abergin,ou=People,dc=domain,dc=com
+cn: Andy Bergin
+sn: Bergin
+givenname: Andy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: abergin
+mail: abergin@domain.com
+telephonenumber: +1 408 555 8585
+facsimiletelephonenumber: +1 408 555 7472
+roomnumber: 3472
+userpassword: inflict
+
+dn: uid=dmiller,ou=People,dc=domain,dc=com
+cn: David Miller
+sn: Miller
+givenname: David
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: dmiller
+mail: dmiller@domain.com
+telephonenumber: +1 408 555 9423
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 4135
+userpassword: gosling
+
+dn: uid=gfarmer,ou=People,dc=domain,dc=com
+cn: Gern Farmer
+sn: Farmer
+givenname: Gern
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Cupertino
+uid: gfarmer
+mail: gfarmer@domain.com
+telephonenumber: +1 408 555 6201
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1269
+userpassword: ruling
+
+dn: uid=kwinters,ou=People,dc=domain,dc=com
+cn: Kelly Winters
+sn: Winters
+givenname: Kelly
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: kwinters
+mail: kwinters@domain.com
+telephonenumber: +1 408 555 9069
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4178
+userpassword: forsook
+
+dn: uid=trigden,ou=People,dc=domain,dc=com
+cn: Torrey Rigden
+sn: Rigden
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: trigden
+mail: trigden@domain.com
+telephonenumber: +1 408 555 9280
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 3584
+userpassword: sensitive
+
+dn: uid=cschmith,ou=People,dc=domain,dc=com
+cn: Chris Schmith
+sn: Schmith
+givenname: Chris
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: cschmith
+mail: cschmith@domain.com
+telephonenumber: +1 408 555 8011
+facsimiletelephonenumber: +1 408 555 4774
+roomnumber: 0416
+userpassword: hypotenuse
+
+dn: uid=jwallace,ou=People,dc=domain,dc=com
+cn: Judy Wallace
+sn: Wallace
+givenname: Judy
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Accounting
+ou: People
+l: Sunnyvale
+uid: jwallace
+mail: jwallace@domain.com
+telephonenumber: +1 408 555 0319
+facsimiletelephonenumber: +1 408 555 8473
+roomnumber: 1033
+userpassword: linear
+
+dn: uid=jwalker,ou=People,dc=domain,dc=com
+cn: John Walker
+sn: Walker
+givenname: John
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Cupertino
+uid: jwalker
+mail: jwalker@domain.com
+telephonenumber: +1 408 555 1476
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 3915
+userpassword: dogleg
+
+dn: uid=tclow,ou=People,dc=domain,dc=com
+cn: Torrey Clow
+sn: Clow
+givenname: Torrey
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Santa Clara
+uid: tclow
+mail: tclow@domain.com
+telephonenumber: +1 408 555 8825
+facsimiletelephonenumber: +1 408 555 1992
+roomnumber: 4376
+userpassword: cardreader
+
+dn: uid=bparker,ou=People,dc=domain,dc=com
+cn: Barry Parker
+sn: Parker
+givenname: Barry
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: bparker
+mail: bparker@domain.com
+telephonenumber: +1 408 555 4647
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 1148
+userpassword: lenticular
+
+dn: uid=ealexand,ou=People,dc=domain,dc=com
+cn: Erin Alexander
+sn: Alexander
+givenname: Erin
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: ealexand
+mail: ealexand@domain.com
+telephonenumber: +1 408 555 5563
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 2434
+userpassword: galactose
+
+dn: uid=mtyler,ou=People,dc=domain,dc=com
+cn: Matthew Tyler
+sn: Tyler
+givenname: Matthew
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Human Resources
+ou: People
+l: Cupertino
+uid: mtyler
+mail: mtyler@domain.com
+telephonenumber: +1 408 555 7907
+facsimiletelephonenumber: +1 408 555 4661
+roomnumber: 2701
+userpassword: instantiate
+
+dn: uid=elott,ou=People,dc=domain,dc=com
+cn: Emanuel Lott
+sn: Lott
+givenname: Emanuel
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Testing
+ou: People
+l: Santa Clara
+uid: elott
+mail: elott@domain.com
+telephonenumber: +1 408 555 0932
+facsimiletelephonenumber: +1 408 555 9751
+roomnumber: 3906
+userpassword: holdout
+
+dn: uid=cnewport,ou=People,dc=domain,dc=com
+cn: Christoph Newport
+sn: Newport
+givenname: Christoph
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Sunnyvale
+uid: cnewport
+mail: cnewport@domain.com
+telephonenumber: +1 408 555 0066
+facsimiletelephonenumber: +1 408 555 9332
+roomnumber: 0056
+userpassword: expertise
+
+dn: uid=jvedder,ou=People,dc=domain,dc=com
+cn: Jeff Vedder
+sn: Vedder
+givenname: Jeff
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+ou: Product Development
+ou: People
+l: Santa Clara
+uid: jvedder
+mail: jvedder@domain.com
+telephonenumber: +1 408 555 4668
+facsimiletelephonenumber: +1 408 555 0111
+roomnumber: 3445
+userpassword: befitting
+
+dn: cn=Accounting Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: Accounting Managers
+ou: Groups
+uniquemember: uid=scarter,ou=People,dc=domain,dc=com
+uniquemember: uid=tmorris,ou=People,dc=domain,dc=com
+description: People who can manage accounting entries
+
+dn: cn=HR Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: HR Managers
+ou: Groups
+uniquemember: uid=kvaughan,ou=People,dc=domain,dc=com
+uniquemember: uid=cschmith,ou=People,dc=domain,dc=com
+description: People who can manage HR entries
+
+dn: cn=QA Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: QA Managers
+ou: Groups
+uniquemember: uid=abergin,ou=People,dc=domain,dc=com
+uniquemember: uid=jwalker,ou=People,dc=domain,dc=com
+description: People who can manage QA entries
+
+dn: cn=PD Managers,ou=Groups,dc=domain,dc=com
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: PD Managers
+ou: Groups
+uniquemember: uid=kwinters,ou=People,dc=domain,dc=com
+uniquemember: uid=trigden,ou=People,dc=domain,dc=com
+description: People who can manage engineer entries
+
+dn: ou=Netscape Servers,dc=domain,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: Netscape Servers
+description: Standard branch for Netscape Server registration
+

Added: incubator/directory/eve/branches/start/src/schema/corba.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/corba.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,222 @@
+# Corba Object Schema
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/corba.schema,v 1.1.2.1 2000/09/13 00:42:36 kurt Exp $
+# depends upon core.schema
+
+# Network Working Group                                            V. Ryan
+# Request for Comments: 2714                                        R. Lee
+# Category: Informational                                      S. Seligman
+#                                                   Sun Microsystems, Inc.
+#                                                             October 1999
+# 
+# 
+#   Schema for Representing CORBA Object References in an LDAP Directory
+# 
+# Status of this Memo
+# 
+#    This memo provides information for the Internet community.  It does
+#    not specify an Internet standard of any kind.  Distribution of this
+#    memo is unlimited.
+# 
+# Copyright Notice
+# 
+#    Copyright (C) The Internet Society (1999).  All Rights Reserved.
+# 
+# Abstract
+# 
+#    CORBA [CORBA] is the Common Object Request Broker Architecture
+#    defined by the Object Management Group. This document defines the
+#    schema for representing CORBA object references in an LDAP directory
+#    [LDAPv3].
+# 
+# [trimmed]
+
+# 3. Attribute Type Definitions
+# 
+#    The following attribute types are defined in this document:
+# 
+#        corbaIor
+#        corbaRepositoryId
+# 
+# 3.1 corbaIor
+# 
+#    This attribute stores the string representation of the interoperable
+#    object reference (IOR) for a CORBA object. An IOR is an opaque handle
+#    for the object which contains the information necessary to locate the
+#    object, even if the object is in another ORB.
+# 
+#    This attribute's syntax is 'IA5 String' and its case is
+#    insignificant.
+# 
+#    ( 1.3.6.1.4.1.42.2.27.4.1.14
+#     NAME 'corbaIor'
+#     DESC 'Stringified interoperable object reference of a CORBA object'
+#     EQUALITY caseIgnoreIA5Match
+#     SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+#     SINGLE-VALUE
+#    )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.14
+	NAME 'corbaIor'
+	DESC 'Stringified interoperable object reference of a CORBA object'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+	SINGLE-VALUE )
+
+# 3.2 corbaRepositoryId
+# 
+#    Each CORBA interface has a unique "repository id" (also called "type
+#    id") that identifies the interface.  A CORBA object has one or more
+#    repository ids, one for each interface that it implements.
+# 
+#    The format of a repository id can be any string, but the OMG
+#    specifies four standard formats:
+# 
+#       a. IDL-style
+# 
+#        IDL:Prefix/ModuleName/InterfaceName:VersionNumber
+# 
+#    For example, the repository id for the "NamingContext" in OMG's COS
+#    Naming module is:  "IDL:omg.org/CosNaming/NamingContext:1.0".
+# 
+#       b. RMI-style
+# 
+#        RMI:ClassName:HashCode[:SUID]
+# 
+#    This format is used by RMI-IIOP remote objects [RMI-IIOP].
+#    "ClassName" is the fully qualified name of the class (for example,
+#    "java.lang.String"). "HashCode" is the object's hash code (that is,
+#    that obtained by invoking the "hashCode()" method).  "SUID" is the
+#    "stream unique identifier", which is a 64-bit number that uniquely
+#    identifies the serialization version of the class; SUID is optional
+#    in the repository id.
+# 
+#       c. DCE-style
+# 
+#        DCE:UUID
+# 
+#    This format is used for DCE/CORBA interoperability [CORBA-DCE].
+#    "UUID" represents a DCE UUID.
+# 
+#       d. "local"
+# 
+#    This format is defined by the local Object Request Broker (ORB).
+# 
+#    The corbaRepositoryId attribute is a multivalued attribute; each
+#    value records a single repository id of an interface implemented by
+#    the CORBA object.  This attribute need not contain a complete list of
+#    the interfaces implemented by the CORBA object.
+# 
+#    This attribute's syntax is 'Directory String' and its case is
+#    significant.  The values of this attribute are encoded using UTF-8.
+#    Some values may require translation from their native representation
+#    in order to be correctly encoded using UTF-8.
+# 
+#    ( 1.3.6.1.4.1.42.2.27.4.1.15
+#     NAME 'corbaRepositoryId'
+#     DESC 'Repository ids of interfaces implemented by a CORBA object'
+#     EQUALITY caseExactMatch
+#     SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+#    )
+# 
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.15
+	NAME 'corbaRepositoryId'
+	DESC 'Repository ids of interfaces implemented by a CORBA object'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# 4. Object Class Definitions
+# 
+#    The following object classes are defined in this document:
+# 
+#        corbaContainer
+#        corbaObject
+#        corbaObjectReference
+# 
+# 4.1 corbaContainer
+# 
+#    This structural object class represents a container for a CORBA
+#    object.
+# 
+#    ( 1.3.6.1.4.1.42.2.27.4.2.10
+#     NAME 'corbaContainer'
+#     DESC 'Container for a CORBA object'
+#     SUP top
+#     STRUCTURAL
+#     MUST ( cn )
+#    )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.10
+	NAME 'corbaContainer'
+	DESC 'Container for a CORBA object'
+	SUP top
+	STRUCTURAL
+	MUST cn )
+
+# 4.2 corbaObject
+# 
+#    This abstract object class is the root class for representing a CORBA
+#    object.
+# 
+#    ( 1.3.6.1.4.1.42.2.27.4.2.9
+#     NAME 'corbaObject'
+#     DESC 'CORBA object representation'
+#     SUP top
+#     ABSTRACT
+#     MAY ( corbaRepositoryId $ description )
+#    )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.9
+	NAME 'corbaObject'
+	DESC 'CORBA object representation'
+	SUP top
+	ABSTRACT
+	MAY ( corbaRepositoryId $ description ) )
+
+# 4.3 corbaObjectReference
+# 
+#    This auxiliary object class represents a CORBA object reference.  It
+#    must be mixed in with a structural object class.
+# 
+#    ( 1.3.6.1.4.1.42.2.27.4.2.11
+#     NAME 'corbaObjectReference'
+#     DESC 'CORBA interoperable object reference'
+#     SUP corbaObject
+#     AUXILIARY
+#     MUST ( corbaIor )
+#    )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.11
+	NAME 'corbaObjectReference'
+	DESC 'CORBA interoperable object reference'
+	SUP corbaObject
+	AUXILIARY
+	MUST corbaIor )
+ 
+# 10.  Full Copyright Statement
+# 
+#    Copyright (C) The Internet Society (1999).  All Rights Reserved.
+# 
+#    This document and translations of it may be copied and furnished to
+#    others, and derivative works that comment on or otherwise explain it
+#    or assist in its implementation may be prepared, copied, published
+#    and distributed, in whole or in part, without restriction of any
+#    kind, provided that the above copyright notice and this paragraph are
+#    included on all such copies and derivative works.  However, this
+#    document itself may not be modified in any way, such as by removing
+#    the copyright notice or references to the Internet Society or other
+#    Internet organizations, except as needed for the purpose of
+#    developing Internet standards in which case the procedures for
+#    copyrights defined in the Internet Standards process must be
+#    followed, or as required to translate it into languages other than
+#    English.
+# 
+#    The limited permissions granted above are perpetual and will not be
+#    revoked by the Internet Society or its successors or assigns.
+# 
+#    This document and the information contained herein is provided on an
+#    "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+#    TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+#    BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+#    HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+#    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Added: incubator/directory/eve/branches/start/src/schema/core.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/core.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,606 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/core.schema,v 1.7.2.18 2002/02/08 17:38:54 kurt Exp $
+#
+# OpenLDAP Core schema
+#
+# Includes LDAPv3 schema items from:
+#	RFC2251-RFC2256 (LDAPv3)
+#
+# select standard track schema items:
+#	RFC2079 (URI)
+#	RFC1274 (uid/dc)
+#	RFC2247 (dc/dcObject)
+#	RFC2589 (Dynamic Directory Services)
+#
+# select informational schema items:
+#	RFC2377 (uidObject)
+#
+# select IETF ''work in progress'' LDAPext/LDUP items
+#   ldapSubentry
+#	ldapRootDSE
+#	named referrals
+#	alias draft
+
+# Standard X.501(93) Operational Attribute Types from RFC2252
+
+attributetype ( 2.5.18.1 NAME 'createTimestamp'
+	EQUALITY generalizedTimeMatch
+	ORDERING generalizedTimeOrderingMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.2 NAME 'modifyTimestamp'
+	EQUALITY generalizedTimeMatch
+	ORDERING generalizedTimeOrderingMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.3 NAME 'creatorsName'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.4 NAME 'modifiersName'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.10 NAME 'subschemaSubentry'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
+	SINGLE-VALUE USAGE directoryOperation )
+
+attributetype ( 2.5.21.1 NAME 'dITStructureRules'
+	EQUALITY integerFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 USAGE directoryOperation )
+
+attributetype ( 2.5.21.2 NAME 'dITContentRules'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )
+
+attributetype ( 2.5.21.4 NAME 'matchingRules'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )
+
+attributetype ( 2.5.21.5 NAME 'attributeTypes'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )
+
+attributetype ( 2.5.21.6 NAME 'objectClasses'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )
+
+attributetype ( 2.5.21.7 NAME 'nameForms'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )
+
+attributetype ( 2.5.21.8 NAME 'matchingRuleUse'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )
+
+# From X.500(93)
+attributetype ( 2.5.21.9 NAME 'structuralObjectClass'
+	DESC 'X.500(93) structural object class'
+	EQUALITY objectIdentifierMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38
+	NO-USER-MODIFICATION SINGLE-VALUE USAGE directoryOperation )
+
+# LDAP Operational Attributes from RFC2252
+attributetype ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes'
+	EQUALITY objectIdentifierFirstComponentMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )
+
+# Object Classes from RFC2252
+objectclass ( 2.5.20.1 NAME 'subschema' AUXILIARY
+	DESC 'RFC2252: controlling subschema' 
+	MAY ( dITStructureRules $ nameForms $ ditContentRules $
+		objectClasses $ attributeTypes $ matchingRules $
+		matchingRuleUse ) )
+
+# Standard attribute types used for subtyping from RFC2256
+
+attributetype ( 2.5.4.41 NAME 'name'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attributetype ( 2.5.4.49 NAME 'distinguishedName'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# Standard attribute types from RFC2256
+
+attributetype ( 2.5.4.0 NAME 'objectClass'
+	EQUALITY objectIdentifierMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+attributetype ( 2.5.4.1 NAME 'aliasedObjectName'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+
+# obsolete
+attributetype ( 2.5.4.2 NAME 'knowledgeInformation'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attributetype ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name )
+
+attributetype ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name )
+
+attributetype ( 2.5.4.5 NAME 'serialNumber' EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
+
+# (2-letter code from ISO 3166)
+attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' ) SUP name SINGLE-VALUE )
+
+attributetype ( 2.5.4.7 NAME ( 'l' 'localityName' ) SUP name )
+
+attributetype ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) SUP name )
+
+attributetype ( 2.5.4.9 NAME ( 'street' 'streetAddress' )
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.10 NAME ( 'o' 'organizationName' ) SUP name )
+
+attributetype ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) SUP name )
+
+attributetype ( 2.5.4.12 NAME 'title' SUP name )
+
+attributetype ( 2.5.4.13 NAME 'description'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+
+# Obsoleted by enhancedSearchGuide
+attributetype ( 2.5.4.14 NAME 'searchGuide'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
+
+attributetype ( 2.5.4.15 NAME 'businessCategory'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.16 NAME 'postalAddress'
+	EQUALITY caseIgnoreListMatch
+	SUBSTR caseIgnoreListSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attributetype ( 2.5.4.17 NAME 'postalCode'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attributetype ( 2.5.4.18 NAME 'postOfficeBox'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attributetype ( 2.5.4.19 NAME 'physicalDeliveryOfficeName'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.20 NAME 'telephoneNumber'
+	EQUALITY telephoneNumberMatch
+	SUBSTR telephoneNumberSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
+
+attributetype ( 2.5.4.21 NAME 'telexNumber'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
+
+attributetype ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
+
+attributetype ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
+
+attributetype ( 2.5.4.24 NAME 'x121Address'
+	EQUALITY numericStringMatch
+	SUBSTR numericStringSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
+
+attributetype ( 2.5.4.25 NAME 'internationaliSDNNumber'
+	EQUALITY numericStringMatch
+	SUBSTR numericStringSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
+
+attributetype ( 2.5.4.26 NAME 'registeredAddress' SUP postalAddress
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attributetype ( 2.5.4.27 NAME 'destinationIndicator'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
+
+attributetype ( 2.5.4.28 NAME 'preferredDeliveryMethod'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
+	SINGLE-VALUE )
+
+attributetype ( 2.5.4.29 NAME 'presentationAddress'
+	EQUALITY presentationAddressMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
+	SINGLE-VALUE )
+
+attributetype ( 2.5.4.30 NAME 'supportedApplicationContext'
+	EQUALITY objectIdentifierMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+attributetype ( 2.5.4.31 NAME 'member' SUP distinguishedName )
+
+attributetype ( 2.5.4.32 NAME 'owner' SUP distinguishedName )
+
+attributetype ( 2.5.4.33 NAME 'roleOccupant' SUP distinguishedName )
+
+attributetype ( 2.5.4.34 NAME 'seeAlso' SUP distinguishedName )
+
+attributetype ( 2.5.4.35 NAME 'userPassword'
+	EQUALITY octetStringMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.36 NAME 'userCertificate'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.37 NAME 'cACertificate'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.38 NAME 'authorityRevocationList'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.39 NAME 'certificateRevocationList'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# Must be stored and requested in the binary form
+attributetype ( 2.5.4.40 NAME 'crossCertificatePair'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
+
+# 2.5.4.41 is defined above as it's used for subtyping
+#attributetype ( 2.5.4.41 NAME 'name'
+#	EQUALITY caseIgnoreMatch
+#	SUBSTR caseIgnoreSubstringsMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attributetype ( 2.5.4.42 NAME ( 'givenName' 'gn' ) SUP name )
+
+attributetype ( 2.5.4.43 NAME 'initials' SUP name
+	DESC 'The initials attribute type contains the initials of some
+		or all of an individuals names, but not the surname(s).' )
+
+attributetype ( 2.5.4.44 NAME 'generationQualifier' 
+	DESC 'e.g. Jr or II.'
+	SUP name )
+
+attributetype ( 2.5.4.45 NAME 'x500UniqueIdentifier'
+	EQUALITY bitStringMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
+
+attributetype ( 2.5.4.46 NAME 'dnQualifier'
+	EQUALITY caseIgnoreMatch
+	ORDERING caseIgnoreOrderingMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
+
+attributetype ( 2.5.4.47 NAME 'enhancedSearchGuide'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
+
+attributetype ( 2.5.4.48 NAME 'protocolInformation'
+	EQUALITY protocolInformationMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
+
+# 2.5.4.49 is defined above as it's used for subtyping
+#attributetype ( 2.5.4.49 NAME 'distinguishedName'
+#	EQUALITY distinguishedNameMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 2.5.4.50 NAME 'uniqueMember'
+	EQUALITY uniqueMemberMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
+
+attributetype ( 2.5.4.51 NAME 'houseIdentifier'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.52 NAME 'supportedAlgorithms'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.53 NAME 'deltaRevocationList'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+attributetype ( 2.5.4.54 NAME 'dmdName' SUP name )
+
+# Standard object classes from RFC2256
+
+objectclass ( 2.5.6.0 NAME 'top' ABSTRACT
+	MUST objectClass )
+
+objectclass ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL
+	MUST aliasedObjectName )
+
+objectclass ( 2.5.6.2 NAME 'country' SUP top STRUCTURAL
+	MUST c
+	MAY ( searchGuide $ description ) )
+
+objectclass ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL
+	MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
+
+objectclass ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL
+	MUST o
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL
+	MUST ou
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL
+	MUST ( sn $ cn )
+	MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
+
+objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL
+	MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )
+
+objectclass ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL
+	MUST cn
+	MAY ( x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+		seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
+		postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
+
+objectclass ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL
+	MUST ( member $ cn )
+	MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+objectclass ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL
+	MUST l
+	MAY ( businessCategory $ x121Address $ registeredAddress $
+		destinationIndicator $ preferredDeliveryMethod $ telexNumber $
+		teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
+		postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ st $ l ) )
+
+objectclass ( 2.5.6.11 NAME 'applicationProcess' SUP top STRUCTURAL
+	MUST cn
+	MAY ( seeAlso $ ou $ l $ description ) )
+
+objectclass ( 2.5.6.12 NAME 'applicationEntity' SUP top STRUCTURAL
+	MUST ( presentationAddress $ cn )
+	MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
+	description ) )
+
+objectclass ( 2.5.6.13 NAME 'dSA' SUP applicationEntity STRUCTURAL
+	MAY knowledgeInformation )
+
+objectclass ( 2.5.6.14 NAME 'device' SUP top STRUCTURAL
+	MUST cn
+	MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
+
+objectclass ( 2.5.6.15 NAME 'strongAuthenticationUser' SUP top AUXILIARY
+	MUST userCertificate )
+
+objectclass ( 2.5.6.16 NAME 'certificationAuthority' SUP top AUXILIARY
+	MUST ( authorityRevocationList $ certificateRevocationList $
+		cACertificate ) MAY crossCertificatePair )
+
+objectclass ( 2.5.6.17 NAME 'groupOfUniqueNames' SUP top STRUCTURAL
+	MUST ( uniqueMember $ cn )
+	MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+objectclass ( 2.5.6.18 NAME 'userSecurityInformation' SUP top AUXILIARY
+	MAY ( supportedAlgorithms ) )
+
+objectclass ( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP
+	certificationAuthority
+	AUXILIARY MAY ( deltaRevocationList ) )
+
+objectclass ( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTURAL
+	MUST ( cn )
+	MAY ( certificateRevocationList $ authorityRevocationList $
+		deltaRevocationList ) )
+
+objectclass ( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL
+	MUST ( dmdName )
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+		street $ postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject'
+	DESC 'RFC2252: extensible object'
+	SUP top AUXILIARY )
+
+#
+# Standard Track URI label schema from RFC2079
+#
+attributetype ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI'
+	DESC 'RFC2079: Uniform Resource Identifier with optional label'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+objectclass ( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject'
+	DESC 'RFC2079: object that contains the URI attribute type'
+	MAY ( labeledURI )
+	SUP top AUXILIARY )
+
+#
+# Standard Track Dynamic Directory Services from RFC2589
+#
+objectclass ( 1.3.6.1.4.1.1466.101.119.2 NAME 'dynamicObject'
+	DESC 'RFC2589: Dynamic Object'
+	SUP top AUXILIARY )
+
+attributetype ( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl'
+	DESC 'RFC2589: entry time-to-live'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
+	NO-USER-MODIFICATION USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.1466.101.119.4 NAME 'dynamicSubtrees'
+	DESC 'RFC2589: dynamic subtrees'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
+	USAGE dSAOperation )
+
+#
+# Derived from RFC1274, but with new "short names"
+#
+attributetype ( 0.9.2342.19200300.100.1.1
+	NAME ( 'uid' 'userid' )
+	DESC 'RFC1274: user identifier'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+attributetype ( 0.9.2342.19200300.100.1.3
+	NAME ( 'mail' 'rfc822Mailbox' )
+	DESC 'RFC1274: RFC822 Mailbox'
+    EQUALITY caseIgnoreIA5Match
+    SUBSTR caseIgnoreIA5SubstringsMatch
+    SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+objectclass ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
+	DESC 'RFC1274: simple security object'
+	SUP top AUXILIARY
+	MUST userPassword )
+
+# RFC1274 + RFC2247
+attributetype ( 0.9.2342.19200300.100.1.25
+	NAME ( 'dc' 'domainComponent' )
+	DESC 'RFC1274/2247: domain component'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+# RFC2247
+objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'
+	DESC 'RFC2247: domain component object'
+	SUP top AUXILIARY MUST dc )
+
+
+# From RFC2377
+objectclass ( 1.3.6.1.1.3.1 NAME 'uidObject'
+	DESC 'RFC2377: uid object'
+	SUP top AUXILIARY MUST uid )
+
+#
+# From draft-zeilenga-ldap-nameref-xx.txt
+#	used to represent referrals in the directory
+#
+attributetype ( 2.16.840.1.113730.3.1.34 NAME 'ref'
+	DESC 'Named referral'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	USAGE distributedOperation )
+
+objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
+	DESC 'Named referral object'
+	SUP top STRUCTURAL MUST ref )
+
+#
+# LDAPsubEntry
+#	deprecated!
+objectclass ( 2.16.840.1.113719.2.142.6.1.1
+	NAME 'LDAPsubEntry'
+	DESC 'LDAP Subentry'
+	SUP top STRUCTURAL MAY cn )
+
+#
+# OpenLDAProotDSE
+#	likely to change!
+objectclass ( 1.3.6.1.4.1.4203.1.4.1
+	NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' )
+	DESC 'OpenLDAP Root DSE object'
+	SUP top STRUCTURAL MAY cn )
+
+#
+# From Cosine Pilot
+#
+attributetype ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+#
+# From U-Mich
+#
+attributetype ( 1.3.6.1.4.1.250.1.32
+	NAME ( 'krbName' 'kerberosName' )
+	DESC 'Kerberos Name'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+	SINGLE-VALUE )
+
+#
+# draft-zeilenga-ldap-features-xx.txt (supportedFeatures)
+#
+attributetype ( 1.3.6.1.4.1.4203.1.3.5
+      NAME 'supportedFeatures'
+      DESC 'features supported by the server'
+      EQUALITY objectIdentifierMatch
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.38
+      USAGE dSAOperation )
+
+#
+# OpenLDAP specific schema items
+#
+attributetype ( 1.3.6.1.4.1.4203.1.3.1
+	NAME 'entry'
+	DESC 'OpenLDAP ACL entry pseudo-attribute'
+	SYNTAX 1.3.6.1.4.1.4203.1.1.1
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
+
+attributetype ( 1.3.6.1.4.1.4203.1.3.2
+	NAME 'children'
+	DESC 'OpenLDAP ACL children pseudo-attribute'
+	SYNTAX 1.3.6.1.4.1.4203.1.1.1
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
+
+# Experimental ( subject to change )
+#	this really shouldn't be published!
+attributetype ( 1.3.6.1.4.1.4203.666.1.5
+	NAME 'OpenLDAPaci'
+	DESC 'OpenLDAP access control information'
+	EQUALITY OpenLDAPaciMatch
+	SYNTAX 1.3.6.1.4.1.4203.666.2.1
+	USAGE directoryOperation )

Added: incubator/directory/eve/branches/start/src/schema/core.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/core.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,1447 @@
+<configuration>
+	<attributetype>
+		<oid>2.5.18.1</oid>
+		<name>
+			<name>'createTimestamp'</name>
+		</name>
+		<equality>generalizedTimeMatch</equality>
+		<ordering>generalizedTimeOrderingMatch</ordering>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.24</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.18.2</oid>
+		<name>
+			<name>'modifyTimestamp'</name>
+		</name>
+		<equality>generalizedTimeMatch</equality>
+		<ordering>generalizedTimeOrderingMatch</ordering>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.24</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.18.3</oid>
+		<name>
+			<name>'creatorsName'</name>
+		</name>
+		<equality>distinguishedNameMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.18.4</oid>
+		<name>
+			<name>'modifiersName'</name>
+		</name>
+		<equality>distinguishedNameMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.18.10</oid>
+		<name>
+			<name>'subschemaSubentry'</name>
+		</name>
+		<equality>distinguishedNameMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<no-user-modification>true</no-user-modification>
+		<single-value>true</single-value>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.1</oid>
+		<name>
+			<name>'dITStructureRules'</name>
+		</name>
+		<equality>integerFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.17</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.2</oid>
+		<name>
+			<name>'dITContentRules'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.16</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.4</oid>
+		<name>
+			<name>'matchingRules'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.30</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.5</oid>
+		<name>
+			<name>'attributeTypes'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.3</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.6</oid>
+		<name>
+			<name>'objectClasses'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.37</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.7</oid>
+		<name>
+			<name>'nameForms'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.35</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.8</oid>
+		<name>
+			<name>'matchingRuleUse'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.31</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.21.9</oid>
+		<name>
+			<name>'structuralObjectClass'</name>
+		</name>
+		<desc>'X.500(93) structural object class'</desc>
+		<equality>objectIdentifierMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+		<no-user-modification>true</no-user-modification>
+		<single-value>true</single-value>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.5</oid>
+		<name>
+			<name>'namingContexts'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.6</oid>
+		<name>
+			<name>'altServer'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.26</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.7</oid>
+		<name>
+			<name>'supportedExtension'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.13</oid>
+		<name>
+			<name>'supportedControl'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.14</oid>
+		<name>
+			<name>'supportedSASLMechanisms'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.15</oid>
+		<name>
+			<name>'supportedLDAPVersion'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.27</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.120.16</oid>
+		<name>
+			<name>'ldapSyntaxes'</name>
+		</name>
+		<equality>objectIdentifierFirstComponentMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.54</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+
+	<objectclass>
+		<id>2.5.20.1</id>
+		<name>
+			<name>'subschema'</name>
+		</name>
+		<auxiliary>true</auxiliary>
+		<desc>'RFC2252: controlling subschema'</desc>
+		<may>
+			<value>dITStructureRules</value>
+			<value>nameForms</value>
+			<value>ditContentRules</value>
+			<value>objectClasses</value>
+			<value>attributeTypes</value>
+			<value>matchingRules</value>
+			<value>matchingRuleUse</value>
+		</may>
+	</objectclass>
+
+	<attributetype>
+		<oid>2.5.4.41</oid>
+		<name>
+			<name>'name'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{32768}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.49</oid>
+		<name>
+			<name>'distinguishedName'</name>
+		</name>
+		<equality>distinguishedNameMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.0</oid>
+		<name>
+			<name>'objectClass'</name>
+		</name>
+		<equality>objectIdentifierMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.1</oid>
+		<name>
+			<name>'aliasedObjectName'</name>
+		</name>
+		<equality>distinguishedNameMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.2</oid>
+		<name>
+			<name>'knowledgeInformation'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{32768}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.3</oid>
+		<name>
+			<name>'cn'</name>
+			<name>'commonName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.4</oid>
+		<name>
+			<name>'sn'</name>
+			<name>'surname'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.5</oid>
+		<name>
+			<name>'serialNumber'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.44{64}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.6</oid>
+		<name>
+			<name>'c'</name>
+			<name>'countryName'</name>
+		</name>
+		<sup>name</sup>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.7</oid>
+		<name>
+			<name>'l'</name>
+			<name>'localityName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.8</oid>
+		<name>
+			<name>'st'</name>
+			<name>'stateOrProvinceName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.9</oid>
+		<name>
+			<name>'street'</name>
+			<name>'streetAddress'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{128}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.10</oid>
+		<name>
+			<name>'o'</name>
+			<name>'organizationName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.11</oid>
+		<name>
+			<name>'ou'</name>
+			<name>'organizationalUnitName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.12</oid>
+		<name>
+			<name>'title'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.13</oid>
+		<name>
+			<name>'description'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{1024}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.14</oid>
+		<name>
+			<name>'searchGuide'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.25</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.15</oid>
+		<name>
+			<name>'businessCategory'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{128}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.16</oid>
+		<name>
+			<name>'postalAddress'</name>
+		</name>
+		<equality>caseIgnoreListMatch</equality>
+		<substr>caseIgnoreListSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.41</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.17</oid>
+		<name>
+			<name>'postalCode'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{40}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.18</oid>
+		<name>
+			<name>'postOfficeBox'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{40}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.19</oid>
+		<name>
+			<name>'physicalDeliveryOfficeName'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{128}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.20</oid>
+		<name>
+			<name>'telephoneNumber'</name>
+		</name>
+		<equality>telephoneNumberMatch</equality>
+		<substr>telephoneNumberSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.50{32}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.21</oid>
+		<name>
+			<name>'telexNumber'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.52</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.22</oid>
+		<name>
+			<name>'teletexTerminalIdentifier'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.51</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.23</oid>
+		<name>
+			<name>'facsimileTelephoneNumber'</name>
+			<name>'fax'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.22</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.24</oid>
+		<name>
+			<name>'x121Address'</name>
+		</name>
+		<equality>numericStringMatch</equality>
+		<substr>numericStringSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.36{15}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.25</oid>
+		<name>
+			<name>'internationaliSDNNumber'</name>
+		</name>
+		<equality>numericStringMatch</equality>
+		<substr>numericStringSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.36{16}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.26</oid>
+		<name>
+			<name>'registeredAddress'</name>
+		</name>
+		<sup>postalAddress</sup>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.41</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.27</oid>
+		<name>
+			<name>'destinationIndicator'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.44{128}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.28</oid>
+		<name>
+			<name>'preferredDeliveryMethod'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.14</syntax>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.29</oid>
+		<name>
+			<name>'presentationAddress'</name>
+		</name>
+		<equality>presentationAddressMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.43</syntax>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.30</oid>
+		<name>
+			<name>'supportedApplicationContext'</name>
+		</name>
+		<equality>objectIdentifierMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.31</oid>
+		<name>
+			<name>'member'</name>
+		</name>
+		<sup>distinguishedName</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.32</oid>
+		<name>
+			<name>'owner'</name>
+		</name>
+		<sup>distinguishedName</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.33</oid>
+		<name>
+			<name>'roleOccupant'</name>
+		</name>
+		<sup>distinguishedName</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.34</oid>
+		<name>
+			<name>'seeAlso'</name>
+		</name>
+		<sup>distinguishedName</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.35</oid>
+		<name>
+			<name>'userPassword'</name>
+		</name>
+		<equality>octetStringMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.40{128}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.36</oid>
+		<name>
+			<name>'userCertificate'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.8</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.37</oid>
+		<name>
+			<name>'cACertificate'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.8</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.38</oid>
+		<name>
+			<name>'authorityRevocationList'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.9</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.39</oid>
+		<name>
+			<name>'certificateRevocationList'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.9</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.40</oid>
+		<name>
+			<name>'crossCertificatePair'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.10</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.42</oid>
+		<name>
+			<name>'givenName'</name>
+			<name>'gn'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.43</oid>
+		<name>
+			<name>'initials'</name>
+		</name>
+		<sup>name</sup>
+		<desc>'The initials attribute type contains the initials of some		or all of an individuals names, but not the surname(s).'</desc>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.44</oid>
+		<name>
+			<name>'generationQualifier'</name>
+		</name>
+		<desc>'e.g. Jr or II.'</desc>
+		<sup>name</sup>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.45</oid>
+		<name>
+			<name>'x500UniqueIdentifier'</name>
+		</name>
+		<equality>bitStringMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.6</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.46</oid>
+		<name>
+			<name>'dnQualifier'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<ordering>caseIgnoreOrderingMatch</ordering>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.44</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.47</oid>
+		<name>
+			<name>'enhancedSearchGuide'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.21</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.48</oid>
+		<name>
+			<name>'protocolInformation'</name>
+		</name>
+		<equality>protocolInformationMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.42</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.50</oid>
+		<name>
+			<name>'uniqueMember'</name>
+		</name>
+		<equality>uniqueMemberMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.34</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.51</oid>
+		<name>
+			<name>'houseIdentifier'</name>
+		</name>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{32768}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.52</oid>
+		<name>
+			<name>'supportedAlgorithms'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.49</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.53</oid>
+		<name>
+			<name>'deltaRevocationList'</name>
+		</name>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.9</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>2.5.4.54</oid>
+		<name>
+			<name>'dmdName'</name>
+		</name>
+		<sup>name</sup>
+	</attributetype>
+
+	<objectclass>
+		<id>2.5.6.0</id>
+		<name>
+			<name>'top'</name>
+		</name>
+		<abstract>true</abstract>
+		<must>
+			<value>objectClass</value>
+		</must>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.1</id>
+		<name>
+			<name>'alias'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>aliasedObjectName</value>
+		</must>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.2</id>
+		<name>
+			<name>'country'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>c</value>
+		</must>
+		<may>
+			<value>searchGuide</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.3</id>
+		<name>
+			<name>'locality'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<may>
+			<value>street</value>
+			<value>seeAlso</value>
+			<value>searchGuide</value>
+			<value>st</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.4</id>
+		<name>
+			<name>'organization'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>o</value>
+		</must>
+		<may>
+			<value>userPassword</value>
+			<value>searchGuide</value>
+			<value>seeAlso</value>
+			<value>businessCategory</value>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>st</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.5</id>
+		<name>
+			<name>'organizationalUnit'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>ou</value>
+		</must>
+		<may>
+			<value>userPassword</value>
+			<value>searchGuide</value>
+			<value>seeAlso</value>
+			<value>businessCategory</value>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>st</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.6</id>
+		<name>
+			<name>'person'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>sn</value>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>userPassword</value>
+			<value>telephoneNumber</value>
+			<value>seeAlso</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.7</id>
+		<name>
+			<name>'organizationalPerson'</name>
+		</name>
+		<sup>person</sup>
+		<structural>true</structural>
+		<may>
+			<value>title</value>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>ou</value>
+			<value>st</value>
+			<value>l</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.8</id>
+		<name>
+			<name>'organizationalRole'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>seeAlso</value>
+			<value>roleOccupant</value>
+			<value>preferredDeliveryMethod</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>ou</value>
+			<value>st</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.9</id>
+		<name>
+			<name>'groupOfNames'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>member</value>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>businessCategory</value>
+			<value>seeAlso</value>
+			<value>owner</value>
+			<value>ou</value>
+			<value>o</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.10</id>
+		<name>
+			<name>'residentialPerson'</name>
+		</name>
+		<sup>person</sup>
+		<structural>true</structural>
+		<must>
+			<value>l</value>
+		</must>
+		<may>
+			<value>businessCategory</value>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>preferredDeliveryMethod</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>st</value>
+			<value>l</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.11</id>
+		<name>
+			<name>'applicationProcess'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>seeAlso</value>
+			<value>ou</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.12</id>
+		<name>
+			<name>'applicationEntity'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>presentationAddress</value>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>supportedApplicationContext</value>
+			<value>seeAlso</value>
+			<value>ou</value>
+			<value>o</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.13</id>
+		<name>
+			<name>'dSA'</name>
+		</name>
+		<sup>applicationEntity</sup>
+		<structural>true</structural>
+		<may>
+			<value>knowledgeInformation</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.14</id>
+		<name>
+			<name>'device'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>serialNumber</value>
+			<value>seeAlso</value>
+			<value>owner</value>
+			<value>ou</value>
+			<value>o</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.15</id>
+		<name>
+			<name>'strongAuthenticationUser'</name>
+		</name>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<must>
+			<value>userCertificate</value>
+		</must>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.16</id>
+		<name>
+			<name>'certificationAuthority'</name>
+		</name>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<must>
+			<value>authorityRevocationList</value>
+			<value>certificateRevocationList</value>
+			<value>cACertificate</value>
+		</must>
+		<may>
+			<value>crossCertificatePair</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.17</id>
+		<name>
+			<name>'groupOfUniqueNames'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>uniqueMember</value>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>businessCategory</value>
+			<value>seeAlso</value>
+			<value>owner</value>
+			<value>ou</value>
+			<value>o</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.18</id>
+		<name>
+			<name>'userSecurityInformation'</name>
+		</name>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<may>
+			<value>supportedAlgorithms</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.16.2</id>
+		<name>
+			<name>'certificationAuthority-V2'</name>
+		</name>
+		<sup>certificationAuthority</sup>
+		<auxiliary>true</auxiliary>
+		<may>
+			<value>deltaRevocationList</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.19</id>
+		<name>
+			<name>'cRLDistributionPoint'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>cn</value>
+		</must>
+		<may>
+			<value>certificateRevocationList</value>
+			<value>authorityRevocationList</value>
+			<value>deltaRevocationList</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>2.5.6.20</id>
+		<name>
+			<name>'dmd'</name>
+		</name>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>dmdName</value>
+		</must>
+		<may>
+			<value>userPassword</value>
+			<value>searchGuide</value>
+			<value>seeAlso</value>
+			<value>businessCategory</value>
+			<value>x121Address</value>
+			<value>registeredAddress</value>
+			<value>destinationIndicator</value>
+			<value>preferredDeliveryMethod</value>
+			<value>telexNumber</value>
+			<value>teletexTerminalIdentifier</value>
+			<value>telephoneNumber</value>
+			<value>internationaliSDNNumber</value>
+			<value>facsimileTelephoneNumber</value>
+			<value>street</value>
+			<value>postOfficeBox</value>
+			<value>postalCode</value>
+			<value>postalAddress</value>
+			<value>physicalDeliveryOfficeName</value>
+			<value>st</value>
+			<value>l</value>
+			<value>description</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>1.3.6.1.4.1.1466.101.120.111</id>
+		<name>
+			<name>'extensibleObject'</name>
+		</name>
+		<desc>'RFC2252: extensible object'</desc>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+	</objectclass>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.250.1.57</oid>
+		<name>
+			<name>'labeledURI'</name>
+		</name>
+		<desc>'RFC2079: Uniform Resource Identifier with optional label'</desc>
+		<equality>caseExactMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15</syntax>
+	</attributetype>
+
+	<objectclass>
+		<id>1.3.6.1.4.1.250.3.15</id>
+		<name>
+			<name>'labeledURIObject'</name>
+		</name>
+		<desc>'RFC2079: object that contains the URI attribute type'</desc>
+		<may>
+			<value>labeledURI</value>
+		</may>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+	</objectclass>
+
+	<objectclass>
+		<id>1.3.6.1.4.1.1466.101.119.2</id>
+		<name>
+			<name>'dynamicObject'</name>
+		</name>
+		<desc>'RFC2589: Dynamic Object'</desc>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+	</objectclass>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.119.3</oid>
+		<name>
+			<name>'entryTtl'</name>
+		</name>
+		<desc>'RFC2589: entry time-to-live'</desc>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.27</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.1466.101.119.4</oid>
+		<name>
+			<name>'dynamicSubtrees'</name>
+		</name>
+		<desc>'RFC2589: dynamic subtrees'</desc>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.12</syntax>
+		<no-user-modification>true</no-user-modification>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>0.9.2342.19200300.100.1.1</oid>
+		<name>
+			<name>'uid'</name>
+			<name>'userid'</name>
+		</name>
+		<desc>'RFC1274: user identifier'</desc>
+		<equality>caseIgnoreMatch</equality>
+		<substr>caseIgnoreSubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15{256}</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>0.9.2342.19200300.100.1.3</oid>
+		<name>
+			<name>'mail'</name>
+			<name>'rfc822Mailbox'</name>
+		</name>
+		<desc>'RFC1274: RFC822 Mailbox'</desc>
+		<equality>caseIgnoreIA5Match</equality>
+		<substr>caseIgnoreIA5SubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.26{256}</syntax>
+	</attributetype>
+
+	<objectclass>
+		<id>0.9.2342.19200300.100.4.19</id>
+		<name>
+			<name>'simpleSecurityObject'</name>
+		</name>
+		<desc>'RFC1274: simple security object'</desc>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<must>
+			<value>userPassword</value>
+		</must>
+	</objectclass>
+
+	<attributetype>
+		<oid>0.9.2342.19200300.100.1.25</oid>
+		<name>
+			<name>'dc'</name>
+			<name>'domainComponent'</name>
+		</name>
+		<desc>'RFC1274/2247: domain component'</desc>
+		<equality>caseIgnoreIA5Match</equality>
+		<substr>caseIgnoreIA5SubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.26</syntax>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<objectclass>
+		<id>1.3.6.1.4.1.1466.344</id>
+		<name>
+			<name>'dcObject'</name>
+		</name>
+		<desc>'RFC2247: domain component object'</desc>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<must>
+			<value>dc</value>
+		</must>
+	</objectclass>
+
+	<objectclass>
+		<id>1.3.6.1.1.3.1</id>
+		<name>
+			<name>'uidObject'</name>
+		</name>
+		<desc>'RFC2377: uid object'</desc>
+		<sup>top</sup>
+		<auxiliary>true</auxiliary>
+		<must>
+			<value>uid</value>
+		</must>
+	</objectclass>
+
+	<attributetype>
+		<oid>2.16.840.1.113730.3.1.34</oid>
+		<name>
+			<name>'ref'</name>
+		</name>
+		<desc>'Named referral'</desc>
+		<equality>caseExactMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.15</syntax>
+		<usage>distributedOperation</usage>
+	</attributetype>
+
+	<objectclass>
+		<id>2.16.840.1.113730.3.2.6</id>
+		<name>
+			<name>'referral'</name>
+		</name>
+		<desc>'Named referral object'</desc>
+		<sup>top</sup>
+		<structural>true</structural>
+		<must>
+			<value>ref</value>
+		</must>
+	</objectclass>
+
+	<objectclass>
+		<id>2.16.840.1.113719.2.142.6.1.1</id>
+		<name>
+			<name>'LDAPsubEntry'</name>
+		</name>
+		<desc>'LDAP Subentry'</desc>
+		<sup>top</sup>
+		<structural>true</structural>
+		<may>
+			<value>cn</value>
+		</may>
+	</objectclass>
+
+	<objectclass>
+		<id>1.3.6.1.4.1.4203.1.4.1</id>
+		<name>
+			<name>'OpenLDAProotDSE'</name>
+			<name>'LDAProotDSE'</name>
+		</name>
+		<desc>'OpenLDAP Root DSE object'</desc>
+		<sup>top</sup>
+		<structural>true</structural>
+		<may>
+			<value>cn</value>
+		</may>
+	</objectclass>
+
+	<attributetype>
+		<oid>0.9.2342.19200300.100.1.37</oid>
+		<name>
+			<name>'associatedDomain'</name>
+		</name>
+		<equality>caseIgnoreIA5Match</equality>
+		<substr>caseIgnoreIA5SubstringsMatch</substr>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.26</syntax>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.250.1.32</oid>
+		<name>
+			<name>'krbName'</name>
+			<name>'kerberosName'</name>
+		</name>
+		<desc>'Kerberos Name'</desc>
+		<equality>caseIgnoreIA5Match</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.26</syntax>
+		<single-value>true</single-value>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.4203.1.3.5</oid>
+		<name>
+			<name>'supportedFeatures'</name>
+		</name>
+		<desc>'features supported by the server'</desc>
+		<equality>objectIdentifierMatch</equality>
+		<syntax>1.3.6.1.4.1.1466.115.121.1.38</syntax>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.4203.1.3.1</oid>
+		<name>
+			<name>'entry'</name>
+		</name>
+		<desc>'OpenLDAP ACL entry pseudo-attribute'</desc>
+		<syntax>1.3.6.1.4.1.4203.1.1.1</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.4203.1.3.2</oid>
+		<name>
+			<name>'children'</name>
+		</name>
+		<desc>'OpenLDAP ACL children pseudo-attribute'</desc>
+		<syntax>1.3.6.1.4.1.4203.1.1.1</syntax>
+		<single-value>true</single-value>
+		<no-user-modification>true</no-user-modification>
+		<usage>dSAOperation</usage>
+	</attributetype>
+
+	<attributetype>
+		<oid>1.3.6.1.4.1.4203.666.1.5</oid>
+		<name>
+			<name>'OpenLDAPaci'</name>
+		</name>
+		<desc>'OpenLDAP access control information'</desc>
+		<equality>OpenLDAPaciMatch</equality>
+		<syntax>1.3.6.1.4.1.4203.666.2.1</syntax>
+		<usage>directoryOperation</usage>
+	</attributetype>
+</configuration>

Added: incubator/directory/eve/branches/start/src/schema/cosine.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/cosine.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,2525 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/cosine.schema,v 1.6.2.7 2002/01/09 16:49:09 kurt Exp $
+#
+# RFC1274: Cosine and Internet X.500 schema
+#
+# This file contains LDAPv3 schema derived from X.500 COSINE "pilot"
+# schema.  As this schema was defined for X.500(89), some
+# oddities were introduced in the mapping to LDAPv3.  The
+# mappings were based upon: draft-ietf-asid-ldapv3-attributes-03.txt
+# (a work in progress)
+#
+# Note: It seems that the pilot schema evolved beyond what was
+# described in RFC1274.  However, this document attempts to describes
+# RFC1274 as published. 
+#
+# Depends on core.schema
+
+
+# Network Working Group                                          P. Barker
+# Request for Comments: 1274                                      S. Kille
+#                                              University College London
+#                                                          November 1991
+#
+#                 The COSINE and Internet X.500 Schema
+#
+# [trimmed]
+#
+# Abstract
+#
+#  This document suggests an X.500 Directory Schema, or Naming
+#  Architecture, for use in the COSINE and Internet X.500 pilots.  The
+#  schema is independent of any specific implementation.  As well as
+#  indicating support for the standard object classes and attributes, a
+#  large number of generally useful object classes and attributes are
+#  also defined.  An appendix to this document includes a machine
+#  processable version of the schema.
+#
+# [trimmed]
+
+# 7.  Object Identifiers
+#
+#  Some additional object identifiers are defined for this schema.
+#  These are also reproduced in Appendix C.
+#
+#    data OBJECT IDENTIFIER ::= {ccitt 9}
+#    pss OBJECT IDENTIFIER ::= {data 2342}
+#    ucl OBJECT IDENTIFIER ::= {pss 19200300}
+#    pilot OBJECT IDENTIFIER ::= {ucl 100}
+#
+#    pilotAttributeType OBJECT IDENTIFIER ::= {pilot 1}
+#    pilotAttributeSyntax OBJECT IDENTIFIER ::= {pilot 3}
+#    pilotObjectClass OBJECT IDENTIFIER ::= {pilot 4}
+#    pilotGroups OBJECT IDENTIFIER ::= {pilot 10}
+#
+#    iA5StringSyntax OBJECT IDENTIFIER ::= {pilotAttributeSyntax 4}
+#    caseIgnoreIA5StringSyntax OBJECT IDENTIFIER ::=
+#                                          {pilotAttributeSyntax 5}
+#
+# 8.  Object Classes
+# [relocated after 9]
+
+#
+# 9.  Attribute Types
+#
+# 9.1.  X.500 standard attribute types
+#
+#  A number of generally useful attribute types are defined in X.520,
+#  and these are supported.  Refer to that document for descriptions of
+#  the suggested usage of these attribute types.  The ASN.1 for these
+#  attribute types is reproduced for completeness in Appendix C.
+#
+# 9.2.  X.400 standard attribute types
+#
+#  The standard X.400 attribute types are supported.  See X.402 for full
+#  details.  The ASN.1 for these attribute types is reproduced in
+#  Appendix C.
+#
+# 9.3.  COSINE/Internet attribute types
+#
+#  This section describes all the attribute types defined for use in the
+#  COSINE and Internet pilots.  Descriptions are given as to the
+#  suggested usage of these attribute types.  The ASN.1 for these
+#  attribute types is reproduced in Appendix C.
+#
+# 9.3.1.  Userid
+#
+#  The Userid attribute type specifies a computer system login name.
+#
+#    userid ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-user-identifier))
+#    ::= {pilotAttributeType 1}
+#
+#(in core.schema)
+##attributetype ( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' )
+##	EQUALITY caseIgnoreMatch
+##	SUBSTR caseIgnoreSubstringsMatch
+##	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.2.  Text Encoded O/R Address
+#
+#  The Text Encoded O/R Address attribute type specifies a text encoding
+#  of an X.400 O/R address, as specified in RFC 987.  The use of this
+#  attribute is deprecated as the attribute is intended for interim use
+#  only.  This attribute will be the first candidate for the attribute
+#  expiry mechanisms!
+#
+#    textEncodedORAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#        (SIZE (1 .. ub-text-encoded-or-address))
+#    ::= {pilotAttributeType 2}
+#
+attributetype ( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORAddress'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.3.  RFC 822 Mailbox
+#
+#  The RFC822 Mailbox attribute type specifies an electronic mailbox
+#  attribute following the syntax specified in RFC 822.  Note that this
+#  attribute should not be used for greybook or other non-Internet order
+#  mailboxes.
+#
+#    rfc822Mailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            (SIZE (1 .. ub-rfc822-mailbox))
+#    ::= {pilotAttributeType 3}
+#
+#(in core.schema)
+##attributetype ( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mailbox' )
+##	EQUALITY caseIgnoreIA5Match
+##	SUBSTR caseIgnoreIA5SubstringsMatch
+##	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+# 9.3.4.  Information
+#
+#  The Information attribute type specifies any general information
+#  pertinent to an object.  It is recommended that specific usage of
+#  this attribute type is avoided, and that specific requirements are
+#  met by other (possibly additional) attribute types.
+#
+#    info ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-information))
+#    ::= {pilotAttributeType 4}
+#
+attributetype ( 0.9.2342.19200300.100.1.4 NAME 'info'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{2048} )
+
+
+# 9.3.5.  Favourite Drink
+#
+#  The Favourite Drink attribute type specifies the favourite drink of
+#  an object (or person).
+#
+#    favouriteDrink ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-favourite-drink))
+#    ::= {pilotAttributeType 5}
+#
+attributetype ( 0.9.2342.19200300.100.1.5
+	NAME ( 'drink' 'favouriteDrink' )
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.6.  Room Number
+#
+#  The Room Number attribute type specifies the room number of an
+#  object.  Note that the commonName attribute should be used for naming
+#  room objects.
+#
+#    roomNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-room-number))
+#    ::= {pilotAttributeType 6}
+#
+attributetype ( 0.9.2342.19200300.100.1.6 NAME 'roomNumber'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.7.  Photo
+#
+#  The Photo attribute type specifies a "photograph" for an object.
+#  This should be encoded in G3 fax as explained in recommendation T.4,
+#  with an ASN.1 wrapper to make it compatible with an X.400 BodyPart as
+#  defined in X.420.
+#
+#    IMPORT  G3FacsimileBodyPart  FROM  {   mhs-motis   ipms   modules
+#    information-objects }
+#
+#    photo ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            CHOICE {
+#                g3-facsimile [3] G3FacsimileBodyPart
+#                }
+#        (SIZE (1 .. ub-photo))
+#    ::= {pilotAttributeType 7}
+#
+attributetype ( 0.9.2342.19200300.100.1.7 NAME 'photo'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.23{25000} )
+
+# 9.3.8.  User Class
+#
+#  The User Class attribute type specifies a category of computer user.
+#  The semantics placed on this attribute are for local interpretation.
+#  Examples of current usage od this attribute in academia are
+#  undergraduate student, researcher, lecturer, etc.  Note that the
+#  organizationalStatus attribute may now often be preferred as it makes
+#  no distinction between computer users and others.
+#
+#    userClass ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-user-class))
+#    ::= {pilotAttributeType 8}
+#
+attributetype ( 0.9.2342.19200300.100.1.8 NAME 'userClass'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.9.  Host
+#
+#  The Host attribute type specifies a host computer.
+#
+#    host ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-host))
+#    ::= {pilotAttributeType 9}
+#
+attributetype ( 0.9.2342.19200300.100.1.9 NAME 'host'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.10.  Manager
+#
+#  The Manager attribute type specifies the manager of an object
+#  represented by an entry.
+#
+#    manager ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 10}
+#
+attributetype ( 0.9.2342.19200300.100.1.10 NAME 'manager'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# 9.3.11.  Document Identifier
+#
+#  The Document Identifier attribute type specifies a unique identifier
+#  for a document.
+#
+#    documentIdentifier ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-identifier))
+#    ::= {pilotAttributeType 11}
+#
+attributetype ( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.12.  Document Title
+#
+#  The Document Title attribute type specifies the title of a document.
+#
+#    documentTitle ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#        (SIZE (1 .. ub-document-title))
+#    ::= {pilotAttributeType 12}
+#
+attributetype ( 0.9.2342.19200300.100.1.12 NAME 'documentTitle'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.13.  Document Version
+#
+#  The Document Version attribute type specifies the version number of a
+#  document.
+#
+#    documentVersion ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-version))
+#    ::= {pilotAttributeType 13}
+#
+attributetype ( 0.9.2342.19200300.100.1.13 NAME 'documentVersion'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.14.  Document Author
+#
+#  The Document Author attribute type specifies the distinguished name
+#  of the author of a document.
+#
+#    documentAuthor ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 14}
+#
+attributetype ( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# 9.3.15.  Document Location
+#
+#  The Document Location attribute type specifies the location of the
+#  document original.
+#
+#    documentLocation ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-location))
+#    ::= {pilotAttributeType 15}
+#
+attributetype ( 0.9.2342.19200300.100.1.15 NAME 'documentLocation'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.16.  Home Telephone Number
+#
+#  The Home Telephone Number attribute type specifies a home telephone
+#  number associated with a person.  Attribute values should follow the
+#  agreed format for international telephone numbers: i.e., "+44 71 123
+#  4567".
+#
+#    homeTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 20}
+#
+attributetype ( 0.9.2342.19200300.100.1.20
+	NAME ( 'homePhone' 'homeTelephoneNumber' )
+	EQUALITY telephoneNumberMatch
+	SUBSTR telephoneNumberSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+# 9.3.17.  Secretary
+#
+#  The Secretary attribute type specifies the secretary of a person.
+#  The attribute value for Secretary is a distinguished name.
+#
+#    secretary ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 21}
+#
+attributetype ( 0.9.2342.19200300.100.1.21 NAME 'secretary'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# 9.3.18.  Other Mailbox
+#
+#  The Other Mailbox attribute type specifies values for electronic
+#  mailbox types other than X.400 and rfc822.
+#
+#    otherMailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            SEQUENCE {
+#                    mailboxType PrintableString, -- e.g. Telemail
+#                    mailbox IA5String  -- e.g. X378:Joe
+#            }
+#    ::= {pilotAttributeType 22}
+#
+attributetype ( 0.9.2342.19200300.100.1.22 NAME 'otherMailbox'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.39 )
+
+# 9.3.19.  Last Modified Time
+#
+#  The Last Modified Time attribute type specifies the last time, in UTC
+#  time, that an entry was modified.  Ideally, this attribute should be
+#  maintained by the DSA.
+#
+#    lastModifiedTime ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            uTCTimeSyntax
+#    ::= {pilotAttributeType 23}
+#
+## OBSOLETE
+#attributetype ( 0.9.2342.19200300.100.1.23 NAME 'lastModifiedTime'
+#	DESC 'RFC1274: time of last modify, replaced by modifyTimestamp'
+#	OBSOLETE
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.53
+#	USAGE directoryOperation )
+
+# 9.3.20.  Last Modified By
+#
+#  The Last Modified By attribute specifies the distinguished name of
+#  the last user to modify the associated entry.  Ideally, this
+#  attribute should be maintained by the DSA.
+#
+#    lastModifiedBy ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 24}
+#
+
+## OBSOLETE
+#attributetype ( 0.9.2342.19200300.100.1.24 NAME 'lastModifiedBy'
+#	DESC 'RFC1274: last modifier, replaced by modifiersName'
+#	OBSOLETE
+#	EQUALITY distinguishedNameMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+#	USAGE directoryOperation )
+
+# 9.3.21.  Domain Component
+#
+#  The Domain Component attribute type specifies a DNS/NRS domain.  For
+#  example, "uk" or "ac".
+#
+#    domainComponent ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            SINGLE VALUE
+#    ::= {pilotAttributeType 25}
+#
+##(in core.schema)
+##attributetype ( 0.9.2342.19200300.100.1.25 NAME ( 'dc' 'domainComponent' )
+##	EQUALITY caseIgnoreIA5Match
+##	SUBSTR caseIgnoreIA5SubstringsMatch
+##	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+# 9.3.22.  DNS ARecord
+#
+#  The A Record attribute type specifies a type A (Address) DNS resource
+#  record [6] [7].
+#
+#    aRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 26}
+#
+## incorrect syntax?
+attributetype ( 0.9.2342.19200300.100.1.26 NAME 'aRecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+## missing from RFC1274
+## incorrect syntax?
+attributetype ( 0.9.2342.19200300.100.1.27 NAME 'mDRecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.23.  MX Record
+#
+#  The MX Record attribute type specifies a type MX (Mail Exchange) DNS
+#  resource record [6] [7].
+#
+#    mXRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 28}
+#
+## incorrect syntax!!
+attributetype ( 0.9.2342.19200300.100.1.28 NAME 'mXRecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.24.  NS Record
+#
+#  The NS Record attribute type specifies an NS (Name Server) DNS
+#  resource record [6] [7].
+#
+#    nSRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 29}
+#
+## incorrect syntax!!
+attributetype ( 0.9.2342.19200300.100.1.29 NAME 'nSRecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.25.  SOA Record
+#
+#  The SOA Record attribute type specifies a type SOA (Start of
+#  Authority) DNS resorce record [6] [7].
+#
+#    sOARecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 30}
+#
+## incorrect syntax!!
+attributetype ( 0.9.2342.19200300.100.1.30 NAME 'sOARecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.26.  CNAME Record
+#
+#  The CNAME Record attribute type specifies a type CNAME (Canonical
+#  Name) DNS resource record [6] [7].
+#
+#    cNAMERecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            iA5StringSyntax
+#    ::= {pilotAttributeType 31}
+#
+## incorrect syntax!!
+attributetype ( 0.9.2342.19200300.100.1.31 NAME 'cNAMERecord'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.27.  Associated Domain
+#
+#  The Associated Domain attribute type specifies a DNS or NRS domain
+#  which is associated with an object in the DIT. For example, the entry
+#  in the DIT with a distinguished name "C=GB, O=University College
+#  London" would have an associated domain of "UCL.AC.UK.  Note that all
+#  domains should be represented in rfc822 order.  See [3] for more
+#  details of usage of this attribute.
+#
+#    associatedDomain ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#    ::= {pilotAttributeType 37}
+#
+#attributetype ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain'
+#	EQUALITY caseIgnoreIA5Match
+#	SUBSTR caseIgnoreIA5SubstringsMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 9.3.28.  Associated Name
+#
+#  The Associated Name attribute type specifies an entry in the
+#  organisational DIT associated with a DNS/NRS domain.  See [3] for
+#  more details of usage of this attribute.
+#
+#    associatedName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 38}
+#
+attributetype ( 0.9.2342.19200300.100.1.38 NAME 'associatedName'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# 9.3.29.  Home postal address
+#
+#  The Home postal address attribute type specifies a home postal
+#  address for an object.  This should be limited to up to 6 lines of 30
+#  characters each.
+#
+#    homePostalAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            postalAddress
+#            MATCHES FOR EQUALITY
+#    ::= {pilotAttributeType 39}
+#
+attributetype ( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress'
+	EQUALITY caseIgnoreListMatch
+	SUBSTR caseIgnoreListSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+# 9.3.30.  Personal Title
+#
+#  The Personal Title attribute type specifies a personal title for a
+#  person. Examples of personal titles are "Ms", "Dr", "Prof" and "Rev".
+#
+#    personalTitle ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-personal-title))
+#    ::= {pilotAttributeType 40}
+#
+attributetype ( 0.9.2342.19200300.100.1.40 NAME 'personalTitle'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.31.  Mobile Telephone Number
+#
+#  The Mobile Telephone Number attribute type specifies a mobile
+#  telephone number associated with a person.  Attribute values should
+#  follow the agreed format for international telephone numbers: i.e.,
+#  "+44 71 123 4567".
+#
+#    mobileTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 41}
+#
+attributetype ( 0.9.2342.19200300.100.1.41
+	NAME ( 'mobile' 'mobileTelephoneNumber' )
+	EQUALITY telephoneNumberMatch
+	SUBSTR telephoneNumberSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+# 9.3.32.  Pager Telephone Number
+#
+#  The Pager Telephone Number attribute type specifies a pager telephone
+#  number for an object. Attribute values should follow the agreed
+#  format for international telephone numbers: i.e., "+44 71 123 4567".
+#
+#    pagerTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 42}
+#
+attributetype ( 0.9.2342.19200300.100.1.42
+	NAME ( 'pager' 'pagerTelephoneNumber' )
+	EQUALITY telephoneNumberMatch
+	SUBSTR telephoneNumberSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )
+
+# 9.3.33.  Friendly Country Name
+#
+#  The Friendly Country Name attribute type specifies names of countries
+#  in human readable format.  The standard attribute country name must
+#  be one of the two-letter codes defined in ISO 3166.
+#
+#    friendlyCountryName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#    ::= {pilotAttributeType 43}
+#
+attributetype ( 0.9.2342.19200300.100.1.43
+	NAME ( 'co' 'friendlyCountryName' )
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# 9.3.34.  Unique Identifier
+#
+#  The Unique Identifier attribute type specifies a "unique identifier"
+#  for an object represented in the Directory.  The domain within which
+#  the identifier is unique, and the exact semantics of the identifier,
+#  are for local definition.  For a person, this might be an
+#  institution-wide payroll number.  For an organisational unit, it
+#  might be a department code.
+#
+#    uniqueIdentifier ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-unique-identifier))
+#    ::= {pilotAttributeType 44}
+#
+attributetype ( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.35.  Organisational Status
+#
+#  The Organisational Status attribute type specifies a category by
+#  which a person is often referred to in an organisation.  Examples of
+#  usage in academia might include undergraduate student, researcher,
+#  lecturer, etc.
+#
+#  A Directory administrator should probably consider carefully the
+#  distinctions between this and the title and userClass attributes.
+#
+#    organizationalStatus ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-organizational-status))
+#    ::= {pilotAttributeType 45}
+#
+attributetype ( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.36.  Janet Mailbox
+#
+#  The Janet Mailbox attribute type specifies an electronic mailbox
+#  attribute following the syntax specified in the Grey Book of the
+#  Coloured Book series.  This attribute is intended for the convenience
+#  of U.K users unfamiliar with rfc822 and little-endian mail addresses.
+#  Entries using this attribute MUST also include an rfc822Mailbox
+#  attribute.
+#
+#    janetMailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            (SIZE (1 .. ub-janet-mailbox))
+#    ::= {pilotAttributeType 46}
+#
+attributetype ( 0.9.2342.19200300.100.1.46 NAME 'janetMailbox'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+# 9.3.37.  Mail Preference Option
+#
+#  An attribute to allow users to indicate a preference for inclusion of
+#  their names on mailing lists (electronic or physical).  The absence
+#  of such an attribute should be interpreted as if the attribute was
+#  present with value "no-list-inclusion".  This attribute should be
+#  interpreted by anyone using the directory to derive mailing lists,
+#  and its value respected.
+#
+#    mailPreferenceOption ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX ENUMERATED {
+#                no-list-inclusion(0),
+#                any-list-inclusion(1),  -- may be added to any lists
+#                professional-list-inclusion(2)
+#                                        -- may be added to lists
+#                                        -- which the list provider
+#                                        -- views as related to the
+#                                        -- users professional inter-
+#                                        -- ests, perhaps evaluated
+#                                        -- from the business of the
+#                                        -- organisation or keywords
+#                                        -- in the entry.
+#                }
+#    ::= {pilotAttributeType 47}
+#
+attributetype ( 0.9.2342.19200300.100.1.47
+	NAME 'mailPreferenceOption'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+# 9.3.38.  Building Name
+#
+#  The Building Name attribute type specifies the name of the building
+#  where an organisation or organisational unit is based.
+#
+#    buildingName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-building-name))
+#    ::= {pilotAttributeType 48}
+#
+attributetype ( 0.9.2342.19200300.100.1.48 NAME 'buildingName'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+# 9.3.39.  DSA Quality
+#
+#  The DSA Quality attribute type specifies the purported quality of a
+#  DSA.  It allows a DSA manager to indicate the expected level of
+#  availability of the DSA. See [8] for details of the syntax.
+#
+#    dSAQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DSAQualitySyntax
+#            SINGLE VALUE
+#    ::= {pilotAttributeType 49}
+#
+attributetype ( 0.9.2342.19200300.100.1.49 NAME 'dSAQuality'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.19 SINGLE-VALUE )
+
+# 9.3.40.  Single Level Quality
+#
+#  The Single Level Quality attribute type specifies the purported data
+#  quality at the level immediately below in the DIT.  See [8] for
+#  details of the syntax.
+#
+#    singleLevelQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#    ::= {pilotAttributeType 50}
+#
+attributetype ( 0.9.2342.19200300.100.1.50 NAME 'singleLevelQuality'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE )
+
+# 9.3.41.  Subtree Minimum Quality
+#
+#  The Subtree Minimum Quality attribute type specifies the purported
+#  minimum data quality for a DIT subtree.  See [8] for more discussion
+#  and details of the syntax.
+#
+#    subtreeMinimumQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#               -- Defaults to singleLevelQuality
+#    ::= {pilotAttributeType 51}
+#
+attributetype ( 0.9.2342.19200300.100.1.51 NAME 'subtreeMinimumQuality'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE )
+
+# 9.3.42.  Subtree Maximum Quality
+#
+#  The Subtree Maximum Quality attribute type specifies the purported
+#  maximum data quality for a DIT subtree.  See [8] for more discussion
+#  and details of the syntax.
+#
+#    subtreeMaximumQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#               -- Defaults to singleLevelQuality
+#    ::= {pilotAttributeType 52}
+#
+attributetype ( 0.9.2342.19200300.100.1.52 NAME 'subtreeMaximumQuality'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE )
+
+# 9.3.43.  Personal Signature
+#
+#  The Personal Signature attribute type allows for a representation of
+#  a person's signature.  This should be encoded in G3 fax as explained
+#  in recommendation T.4, with an ASN.1 wrapper to make it compatible
+#  with an X.400 BodyPart as defined in X.420.
+#
+#    IMPORT  G3FacsimileBodyPart  FROM  {   mhs-motis   ipms   modules
+#    information-objects }
+#
+#    personalSignature ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            CHOICE {
+#                g3-facsimile [3] G3FacsimileBodyPart
+#                }
+#        (SIZE (1 .. ub-personal-signature))
+#    ::= {pilotAttributeType 53}
+#
+attributetype ( 0.9.2342.19200300.100.1.53 NAME 'personalSignature'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.23 )
+
+# 9.3.44.  DIT Redirect
+#
+#  The DIT Redirect attribute type is used to indicate that the object
+#  described by one entry now has a newer entry in the DIT.  The entry
+#  containing the redirection attribute should be expired after a
+#  suitable grace period.  This attribute may be used when an individual
+#  changes his/her place of work, and thus acquires a new organisational
+#  DN.
+#
+#    dITRedirect ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 54}
+#
+attributetype ( 0.9.2342.19200300.100.1.54 NAME 'dITRedirect'
+	 EQUALITY distinguishedNameMatch
+	 SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+# 9.3.45.  Audio
+#
+#  The Audio attribute type allows the storing of sounds in the
+#  Directory.  The attribute uses a u-law encoded sound file as used by
+#  the "play" utility on a Sun 4.  This is an interim format.
+#
+#    audio ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            Audio
+#        (SIZE (1 .. ub-audio))
+#    ::= {pilotAttributeType 55}
+#
+attributetype ( 0.9.2342.19200300.100.1.55 NAME 'audio'
+	 SYNTAX 1.3.6.1.4.1.1466.115.121.1.4{25000} )
+
+# 9.3.46.  Publisher of Document
+#
+#
+#  The Publisher of Document attribute is the person and/or organization
+#  that published a document.
+#
+#    documentPublisher ATTRIBUTE
+#            WITH ATTRIBUTE SYNTAX caseIgnoreStringSyntax
+#    ::= {pilotAttributeType 56}
+#
+attributetype ( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# 9.4.  Generally useful syntaxes
+#
+#    caseIgnoreIA5StringSyntax ATTRIBUTE-SYNTAX
+#            IA5String
+#            MATCHES FOR EQUALITY SUBSTRINGS
+#
+#    iA5StringSyntax ATTRIBUTE-SYNTAX
+#        IA5String
+#        MATCHES FOR EQUALITY SUBSTRINGS
+#
+#
+#    -- Syntaxes to support the DNS attributes
+#
+#    DNSRecordSyntax ATTRIBUTE-SYNTAX
+#            IA5String
+#            MATCHES FOR EQUALITY
+#
+#
+#    NRSInformationSyntax ATTRIBUTE-SYNTAX
+#            NRSInformation
+#            MATCHES FOR EQUALITY
+#
+#
+#    NRSInformation ::=  SET {
+#                    [0] Context,
+#                    [1] Address-space-id,
+#                    routes [2] SEQUENCE OF SEQUENCE {
+#                    Route-cost,
+#                    Addressing-info }
+#            }
+#
+#
+# 9.5.  Upper bounds on length of attribute values
+#
+#
+#    ub-document-identifier INTEGER ::= 256
+#
+#    ub-document-location INTEGER ::= 256
+#
+#    ub-document-title INTEGER ::= 256
+#
+#    ub-document-version INTEGER ::= 256
+#
+#    ub-favourite-drink INTEGER ::= 256
+#
+#    ub-host INTEGER ::= 256
+#
+#    ub-information INTEGER ::= 2048
+#
+#    ub-unique-identifier INTEGER ::= 256
+#
+#    ub-personal-title INTEGER ::= 256
+#
+#    ub-photo INTEGER ::= 250000
+#
+#    ub-rfc822-mailbox INTEGER ::= 256
+#
+#    ub-room-number INTEGER ::= 256
+#
+#    ub-text-or-address INTEGER ::= 256
+#
+#    ub-user-class INTEGER ::= 256
+#
+#    ub-user-identifier INTEGER ::= 256
+#
+#    ub-organizational-status INTEGER ::= 256
+#
+#    ub-janet-mailbox INTEGER ::= 256
+#
+#    ub-building-name INTEGER ::= 256
+#
+#    ub-personal-signature ::= 50000
+#
+#    ub-audio INTEGER ::= 250000
+#
+
+# [back to 8]
+# 8.  Object Classes
+#
+# 8.1.  X.500 standard object classes
+#
+#  A number of generally useful object classes are defined in X.521, and
+#  these are supported.  Refer to that document for descriptions of the
+#  suggested usage of these object classes.  The ASN.1 for these object
+#  classes is reproduced for completeness in Appendix C.
+#
+# 8.2.  X.400 standard object classes
+#
+#  A number of object classes defined in X.400 are supported.  Refer to
+#  X.402 for descriptions of the usage of these object classes.  The
+#  ASN.1 for these object classes is reproduced for completeness in
+#  Appendix C.
+#
+# 8.3.  COSINE/Internet object classes
+#
+#  This section attempts to fuse together the object classes designed
+#  for use in the COSINE and Internet pilot activities.  Descriptions
+#  are given of the suggested usage of these object classes.  The ASN.1
+#  for these object classes is also reproduced in Appendix C.
+#
+# 8.3.1.  Pilot Object
+#
+#  The PilotObject object class is used as a sub-class to allow some
+#  common, useful attributes to be assigned to entries of all other
+#  object classes.
+#
+#    pilotObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MAY CONTAIN {
+#            info,
+#            photo,
+#            manager,
+#            uniqueIdentifier,
+#            lastModifiedTime,
+#            lastModifiedBy,
+#            dITRedirect,
+#            audio}
+#    ::= {pilotObjectClass 3}
+#
+#objectclass ( 0.9.2342.19200300.100.4.3 NAME 'pilotObject'
+#	DESC 'RFC1274: pilot object'
+#	SUP top AUXILIARY
+#	MAY ( info $ photo $ manager $ uniqueIdentifier $
+#		lastModifiedTime $ lastModifiedBy $ dITRedirect $ audio )
+#	)
+
+# 8.3.2.  Pilot Person
+#
+#  The PilotPerson object class is used as a sub-class of person, to
+#  allow the use of a number of additional attributes to be assigned to
+#  entries of object class person.
+#
+#    pilotPerson OBJECT-CLASS
+#        SUBCLASS OF person
+#        MAY CONTAIN {
+#                    userid,
+#                    textEncodedORAddress,
+#                    rfc822Mailbox,
+#                    favouriteDrink,
+#                    roomNumber,
+#                    userClass,
+#                    homeTelephoneNumber,
+#                    homePostalAddress,
+#                    secretary,
+#                    personalTitle,
+#                    preferredDeliveryMethod,
+#                    businessCategory,
+#                    janetMailbox,
+#                    otherMailbox,
+#                    mobileTelephoneNumber,
+#                    pagerTelephoneNumber,
+#                    organizationalStatus,
+#                    mailPreferenceOption,
+#                    personalSignature}
+#    ::= {pilotObjectClass 4}
+#
+objectclass ( 0.9.2342.19200300.100.4.4
+	NAME ( 'pilotPerson' 'newPilotPerson' )
+	SUP person STRUCTURAL
+	MAY ( userid $ textEncodedORAddress $ rfc822Mailbox $
+		favouriteDrink $ roomNumber $ userClass $
+		homeTelephoneNumber $ homePostalAddress $ secretary $
+		personalTitle $ preferredDeliveryMethod $ businessCategory $
+		janetMailbox $ otherMailbox $ mobileTelephoneNumber $
+		pagerTelephoneNumber $ organizationalStatus $
+		mailPreferenceOption $ personalSignature )
+	)
+
+# 8.3.3.  Account
+#
+#  The Account object class is used to define entries representing
+#  computer accounts.  The userid attribute should be used for naming
+#  entries of this object class.
+#
+#    account OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            userid}
+#        MAY CONTAIN {
+#            description,
+#            seeAlso,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            host}
+#    ::= {pilotObjectClass 5}
+#
+objectclass ( 0.9.2342.19200300.100.4.5 NAME 'account'
+	SUP top STRUCTURAL
+	MUST userid
+	MAY ( description $ seeAlso $ localityName $
+		organizationName $ organizationalUnitName $ host )
+	)
+
+# 8.3.4.  Document
+#
+#  The Document object class is used to define entries which represent
+#  documents.
+#
+#    document OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            documentIdentifier}
+#        MAY CONTAIN {
+#            commonName,
+#            description,
+#            seeAlso,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            documentTitle,
+#            documentVersion,
+#            documentAuthor,
+#            documentLocation,
+#            documentPublisher}
+#    ::= {pilotObjectClass 6}
+#
+objectclass ( 0.9.2342.19200300.100.4.6 NAME 'document'
+	SUP top STRUCTURAL
+	MUST documentIdentifier
+	MAY ( commonName $ description $ seeAlso $ localityName $
+		organizationName $ organizationalUnitName $
+		documentTitle $ documentVersion $ documentAuthor $
+		documentLocation $ documentPublisher )
+	)
+
+# 8.3.5.  Room
+#
+#  The Room object class is used to define entries representing rooms.
+#  The commonName attribute should be used for naming pentries of this
+#  object class.
+#
+#    room OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            roomNumber,
+#            description,
+#            seeAlso,
+#            telephoneNumber}
+#    ::= {pilotObjectClass 7}
+#
+objectclass ( 0.9.2342.19200300.100.4.7 NAME 'room'
+	SUP top STRUCTURAL
+	MUST commonName
+	MAY ( roomNumber $ description $ seeAlso $ telephoneNumber )
+	)
+
+# 8.3.6.  Document Series
+#
+#  The Document Series object class is used to define an entry which
+#  represents a series of documents (e.g., The Request For Comments
+#  papers).
+#
+#    documentSeries OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            description,
+#            seeAlso,
+#            telephoneNumber,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName}
+#    ::= {pilotObjectClass 9}
+#
+objectclass ( 0.9.2342.19200300.100.4.9 NAME 'documentSeries'
+	SUP top STRUCTURAL
+	MUST commonName
+	MAY ( description $ seeAlso $ telephonenumber $
+		localityName $ organizationName $ organizationalUnitName )
+	)
+
+# 8.3.7.  Domain
+#
+#  The Domain object class is used to define entries which represent DNS
+#  or NRS domains.  The domainComponent attribute should be used for
+#  naming entries of this object class.  The usage of this object class
+#  is described in more detail in [3].
+#
+#    domain OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            domainComponent}
+#        MAY CONTAIN {
+#            associatedName,
+#            organizationName,
+#            organizationalAttributeSet}
+#    ::= {pilotObjectClass 13}
+#
+objectclass ( 0.9.2342.19200300.100.4.13 NAME 'domain'
+	SUP top STRUCTURAL
+	MUST domainComponent
+	MAY ( associatedName $ organizationName $ description $
+		businessCategory $ seeAlso $ searchGuide $ userPassword $
+		localityName $ stateOrProvinceName $ streetAddress $
+		physicalDeliveryOfficeName $ postalAddress $ postalCode $
+		postOfficeBox $ streetAddress $
+		facsimileTelephoneNumber $ internationalISDNNumber $
+		telephoneNumber $ teletexTerminalIdentifier $ telexNumber $
+		preferredDeliveryMethod $ destinationIndicator $
+		registeredAddress $ x121Address )
+	)
+
+# 8.3.8.  RFC822 Local Part
+#
+#  The RFC822 Local Part object class is used to define entries which
+#  represent the local part of RFC822 mail addresses.  This treats this
+#  part of an RFC822 address as a domain.  The usage of this object
+#  class is described in more detail in [3].
+#
+#    rFC822localPart OBJECT-CLASS
+#        SUBCLASS OF domain
+#        MAY CONTAIN {
+#            commonName,
+#            surname,
+#            description,
+#            seeAlso,
+#            telephoneNumber,
+#            postalAttributeSet,
+#            telecommunicationAttributeSet}
+#    ::= {pilotObjectClass 14}
+#
+objectclass ( 0.9.2342.19200300.100.4.14 NAME 'RFC822localPart'
+	SUP domain STRUCTURAL
+	MAY ( commonName $ surname $ description $ seeAlso $ telephonenumber $
+		physicalDeliveryOfficeName $ postalAddress $ postalCode $
+		postOfficeBox $ streetAddress $
+		facsimileTelephoneNumber $ internationalISDNNumber $
+		telephoneNumber $ teletexTerminalIdentifier $
+		telexNumber $ preferredDeliveryMethod $ destinationIndicator $
+		registeredAddress $ x121Address )
+	)
+
+# 8.3.9.  DNS Domain
+#
+#  The DNS Domain (Domain NameServer) object class is used to define
+#  entries for DNS domains.  The usage of this object class is described
+#  in more detail in [3].
+#
+#    dNSDomain OBJECT-CLASS
+#        SUBCLASS OF domain
+#        MAY CONTAIN {
+#            ARecord,
+#            MDRecord,
+#            MXRecord,
+#            NSRecord,
+#            SOARecord,
+#            CNAMERecord}
+#    ::= {pilotObjectClass 15}
+#
+objectclass ( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain'
+	SUP domain STRUCTURAL
+	MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ 
+		SOARecord $ CNAMERecord )
+	)
+
+# 8.3.10.  Domain Related Object
+#
+#  The Domain Related Object object class is used to define entries
+#  which represent DNS/NRS domains which are "equivalent" to an X.500
+#  domain: e.g., an organisation or organisational unit.  The usage of
+#  this object class is described in more detail in [3].
+#
+#    domainRelatedObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            associatedDomain}
+#    ::= {pilotObjectClass 17}
+#
+objectclass ( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject'
+	SUP top AUXILIARY
+	MUST associatedDomain )
+
+# 8.3.11.  Friendly Country
+#
+#  The Friendly Country object class is used to define country entries
+#  in the DIT.  The object class is used to allow friendlier naming of
+#  countries than that allowed by the object class country.  The naming
+#  attribute of object class country, countryName, has to be a 2 letter
+#  string defined in ISO 3166.
+#
+#    friendlyCountry OBJECT-CLASS
+#        SUBCLASS OF country
+#        MUST CONTAIN {
+#            friendlyCountryName}
+#    ::= {pilotObjectClass 18}
+#
+objectclass ( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry'
+	SUP country STRUCTURAL
+	MUST friendlyCountryName )
+
+# 8.3.12.  Simple Security Object
+#
+#  The Simple Security Object object class is used to allow an entry to
+#  have a userPassword attribute when an entry's principal object
+#  classes do not allow userPassword as an attribute type.
+#
+#    simpleSecurityObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            userPassword }
+#    ::= {pilotObjectClass 19}
+#
+## (in core.schema)
+## objectclass ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
+##	SUP top AUXILIARY
+##	MUST userPassword )
+
+# 8.3.13.  Pilot Organization
+#
+#  The PilotOrganization object class is used as a sub-class of
+#  organization and organizationalUnit to allow a number of additional
+#  attributes to be assigned to entries of object classes organization
+#  and organizationalUnit.
+#
+#    pilotOrganization OBJECT-CLASS
+#        SUBCLASS OF organization, organizationalUnit
+#        MAY CONTAIN {
+#                    buildingName}
+#    ::= {pilotObjectClass 20}
+#
+objectclass ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization'
+	SUP ( organization $ organizationalUnit ) STRUCTURAL
+	MAY buildingName )
+
+# 8.3.14.  Pilot DSA
+#
+#  The PilotDSA object class is used as a sub-class of the dsa object
+#  class to allow additional attributes to be assigned to entries for
+#  DSAs.
+#
+#    pilotDSA OBJECT-CLASS
+#        SUBCLASS OF dsa
+#        MUST CONTAIN {
+#            dSAQuality}
+#    ::= {pilotObjectClass 21}
+#
+objectclass ( 0.9.2342.19200300.100.4.21 NAME 'pilotDSA'
+	SUP dsa STRUCTURAL
+	MAY dSAQuality )
+
+# 8.3.15.  Quality Labelled Data
+#
+#  The Quality Labelled Data object class is used to allow the
+#  assignment of the data quality attributes to subtrees in the DIT.
+#
+#  See [8] for more details.
+#
+#    qualityLabelledData OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            dSAQuality}
+#        MAY CONTAIN {
+#            subtreeMinimumQuality,
+#            subtreeMaximumQuality}
+#    ::= {pilotObjectClass 22}
+objectclass ( 0.9.2342.19200300.100.4.22 NAME 'qualityLabelledData'
+	SUP top AUXILIARY
+	MUST dsaQuality
+	MAY ( subtreeMinimumQuality $ subtreeMaximumQuality )
+	)
+
+
+# References
+#
+#    [1]  CCITT/ISO, "X.500, The Directory - overview of concepts,
+#         models and services, CCITT /ISO IS 9594.
+#
+#    [2]  Kille, S., "The THORN and RARE X.500 Naming Architecture, in
+#         University College London, Department of Computer Science
+#         Research Note 89/48, May 1989.
+#
+#    [3]  Kille, S., "X.500 and Domains", RFC 1279, University College
+#         London, November 1991.
+#
+#    [4]  Rose, M., "PSI/NYSERNet White Pages Pilot Project: Status
+#         Report", Technical Report 90-09-10-1, published by NYSERNet
+#         Inc, 1990.
+#
+#    [5]  Craigie, J., "UK Academic Community Directory Service Pilot
+#         Project, pp. 305-310 in Computer Networks and ISDN Systems
+#         17 (1989), published by North Holland.
+#
+#    [6]  Mockapetris, P., "Domain Names - Concepts and Facilities",
+#         RFC 1034, USC/Information Sciences Institute, November 1987.
+#
+#    [7]  Mockapetris, P., "Domain Names - Implementation and
+#         Specification, RFC 1035, USC/Information Sciences Institute,
+#         November 1987.
+#
+#    [8]  Kille, S., "Handling QOS (Quality of service) in the
+#         Directory," publication in process, March 1991.
+#
+#
+# APPENDIX C - Summary of all Object Classes and Attribute Types
+#
+#    -- Some Important Object Identifiers
+#
+#    data OBJECT IDENTIFIER ::= {ccitt 9}
+#    pss OBJECT IDENTIFIER ::= {data 2342}
+#    ucl OBJECT IDENTIFIER ::= {pss 19200300}
+#    pilot OBJECT IDENTIFIER ::= {ucl 100}
+#
+#    pilotAttributeType OBJECT IDENTIFIER ::= {pilot 1}
+#    pilotAttributeSyntax OBJECT IDENTIFIER ::= {pilot 3}
+#    pilotObjectClass OBJECT IDENTIFIER ::= {pilot 4}
+#    pilotGroups OBJECT IDENTIFIER ::= {pilot 10}
+#
+#    iA5StringSyntax OBJECT IDENTIFIER ::= {pilotAttributeSyntax 4}
+#    caseIgnoreIA5StringSyntax OBJECT IDENTIFIER ::=
+#                                          {pilotAttributeSyntax 5}
+#
+#    -- Standard Object Classes
+#
+#    top OBJECT-CLASS
+#        MUST CONTAIN {
+#            objectClass}
+#    ::= {objectClass 0}
+#
+#
+#    alias OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            aliasedObjectName}
+#    ::= {objectClass 1}
+#
+#
+#    country OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            countryName}
+#        MAY CONTAIN {
+#            description,
+#            searchGuide}
+#    ::= {objectClass 2}
+#
+#
+#    locality OBJECT-CLASS
+#        SUBCLASS OF top
+#        MAY CONTAIN {
+#            description,
+#            localityName,
+#            stateOrProvinceName,
+#            searchGuide,
+#            seeAlso,
+#            streetAddress}
+#    ::= {objectClass 3}
+#
+#
+#    organization OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            organizationName}
+#        MAY CONTAIN {
+#            organizationalAttributeSet}
+#    ::= {objectClass 4}
+#
+#
+#    organizationalUnit OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            organizationalUnitName}
+#        MAY CONTAIN {
+#            organizationalAttributeSet}
+#    ::= {objectClass 5}
+#
+#
+#    person OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName,
+#            surname}
+#        MAY CONTAIN {
+#            description,
+#            seeAlso,
+#            telephoneNumber,
+#            userPassword}
+#    ::= {objectClass 6}
+#
+#
+#    organizationalPerson OBJECT-CLASS
+#        SUBCLASS OF person
+#        MAY CONTAIN {
+#            localeAttributeSet,
+#            organizationalUnitName,
+#            postalAttributeSet,
+#            telecommunicationAttributeSet,
+#            title}
+#    ::= {objectClass 7}
+#
+#
+#    organizationalRole OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            description,
+#            localeAttributeSet,
+#            organizationalUnitName,
+#            postalAttributeSet,
+#            preferredDeliveryMethod,
+#            roleOccupant,
+#            seeAlso,
+#            telecommunicationAttributeSet}
+#    ::= {objectClass 8}
+#
+#
+#    groupOfNames OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName,
+#            member}
+#        MAY CONTAIN {
+#            description,
+#            organizationName,
+#            organizationalUnitName,
+#            owner,
+#            seeAlso,
+#            businessCategory}
+#    ::= {objectClass 9}
+#
+#
+#    residentialPerson OBJECT-CLASS
+#        SUBCLASS OF person
+#        MUST CONTAIN {
+#            localityName}
+#        MAY CONTAIN {
+#            localeAttributeSet,
+#            postalAttributeSet,
+#            preferredDeliveryMethod,
+#            telecommunicationAttributeSet,
+#            businessCategory}
+#    ::= {objectClass 10}
+#
+#
+#    applicationProcess OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            description,
+#            localityName,
+#            organizationalUnitName,
+#            seeAlso}
+#    ::= {objectClass 11}
+#
+#
+#    applicationEntity OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName,
+#            presentationAddress}
+#        MAY CONTAIN {
+#            description,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            seeAlso,
+#            supportedApplicationContext}
+#    ::= {objectClass 12}
+#
+#
+#    dSA OBJECT-CLASS
+#        SUBCLASS OF applicationEntity
+#        MAY CONTAIN {
+#            knowledgeInformation}
+#    ::= {objectClass 13}
+#
+#
+#    device OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            description,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            owner,
+#            seeAlso,
+#            serialNumber}
+#    ::= {objectClass 14}
+#
+#
+#    strongAuthenticationUser OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            userCertificate}
+#    ::= {objectClass 15}
+#
+#
+#    certificationAuthority OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            cACertificate,
+#            certificateRevocationList,
+#            authorityRevocationList}
+#        MAY CONTAIN {
+#            crossCertificatePair}
+#    ::= {objectClass 16}
+#
+#    -- Standard MHS Object Classes
+#
+#    mhsDistributionList OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName,
+#            mhsDLSubmitPermissions,
+#            mhsORAddresses}
+#        MAY CONTAIN {
+#            description,
+#            organizationName,
+#            organizationalUnitName,
+#            owner,
+#            seeAlso,
+#            mhsDeliverableContentTypes,
+#            mhsdeliverableEits,
+#            mhsDLMembers,
+#            mhsPreferredDeliveryMethods}
+#    ::= {mhsObjectClass 0}
+#
+#
+#    mhsMessageStore OBJECT-CLASS
+#        SUBCLASS OF applicationEntity
+#        MAY CONTAIN {
+#            description,
+#            owner,
+#            mhsSupportedOptionalAttributes,
+#            mhsSupportedAutomaticActions,
+#            mhsSupportedContentTypes}
+#    ::= {mhsObjectClass 1}
+#
+#
+#    mhsMessageTransferAgent OBJECT-CLASS
+#        SUBCLASS OF applicationEntity
+#        MAY CONTAIN {
+#            description,
+#            owner,
+#            mhsDeliverableContentLength}
+#    ::= {mhsObjectClass 2}
+#
+#
+#    mhsOrganizationalUser OBJECT-CLASS
+#        SUBCLASS OF organizationalPerson
+#        MUST CONTAIN {
+#            mhsORAddresses}
+#        MAY CONTAIN {
+#            mhsDeliverableContentLength,
+#            mhsDeliverableContentTypes,
+#            mhsDeliverableEits,
+#            mhsMessageStoreName,
+#            mhsPreferredDeliveryMethods }
+#    ::= {mhsObjectClass 3}
+#
+#
+#    mhsResidentialUser OBJECT-CLASS
+#        SUBCLASS OF residentialPerson
+#        MUST CONTAIN {
+#            mhsORAddresses}
+#        MAY CONTAIN {
+#            mhsDeliverableContentLength,
+#            mhsDeliverableContentTypes,
+#            mhsDeliverableEits,
+#            mhsMessageStoreName,
+#            mhsPreferredDeliveryMethods }
+#    ::= {mhsObjectClass 4}
+#
+#
+#    mhsUserAgent OBJECT-CLASS
+#        SUBCLASS OF applicationEntity
+#        MAY CONTAIN {
+#            mhsDeliverableContentLength,
+#            mhsDeliverableContentTypes,
+#            mhsDeliverableEits,
+#            mhsORAddresses,
+#            owner}
+#    ::= {mhsObjectClass 5}
+#
+#
+#
+#
+#    -- Pilot Object Classes
+#
+#    pilotObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MAY CONTAIN {
+#            info,
+#            photo,
+#            manager,
+#            uniqueIdentifier,
+#            lastModifiedTime,
+#            lastModifiedBy,
+#            dITRedirect,
+#            audio}
+#    ::= {pilotObjectClass 3}
+#    pilotPerson OBJECT-CLASS
+#        SUBCLASS OF person
+#        MAY CONTAIN {
+#                    userid,
+#                    textEncodedORAddress,
+#                    rfc822Mailbox,
+#                    favouriteDrink,
+#                    roomNumber,
+#                    userClass,
+#                    homeTelephoneNumber,
+#                    homePostalAddress,
+#                    secretary,
+#                    personalTitle,
+#                    preferredDeliveryMethod,
+#                    businessCategory,
+#                    janetMailbox,
+#                    otherMailbox,
+#                    mobileTelephoneNumber,
+#                    pagerTelephoneNumber,
+#                    organizationalStatus,
+#                    mailPreferenceOption,
+#                    personalSignature}
+#    ::= {pilotObjectClass 4}
+#
+#
+#    account OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            userid}
+#        MAY CONTAIN {
+#            description,
+#            seeAlso,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            host}
+#    ::= {pilotObjectClass 5}
+#
+#
+#    document OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            documentIdentifier}
+#        MAY CONTAIN {
+#            commonName,
+#            description,
+#            seeAlso,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName,
+#            documentTitle,
+#            documentVersion,
+#            documentAuthor,
+#            documentLocation,
+#            documentPublisher}
+#    ::= {pilotObjectClass 6}
+#
+#
+#    room OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            roomNumber,
+#            description,
+#            seeAlso,
+#            telephoneNumber}
+#    ::= {pilotObjectClass 7}
+#
+#
+#    documentSeries OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            commonName}
+#        MAY CONTAIN {
+#            description,
+#            seeAlso,
+#            telephoneNumber,
+#            localityName,
+#            organizationName,
+#            organizationalUnitName}
+#    ::= {pilotObjectClass 9}
+#
+#
+#    domain OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            domainComponent}
+#        MAY CONTAIN {
+#            associatedName,
+#            organizationName,
+#            organizationalAttributeSet}
+#    ::= {pilotObjectClass 13}
+#
+#
+#    rFC822localPart OBJECT-CLASS
+#        SUBCLASS OF domain
+#        MAY CONTAIN {
+#            commonName,
+#            surname,
+#            description,
+#            seeAlso,
+#            telephoneNumber,
+#            postalAttributeSet,
+#            telecommunicationAttributeSet}
+#    ::= {pilotObjectClass 14}
+#
+#
+#    dNSDomain OBJECT-CLASS
+#        SUBCLASS OF domain
+#        MAY CONTAIN {
+#            ARecord,
+#            MDRecord,
+#            MXRecord,
+#            NSRecord,
+#            SOARecord,
+#            CNAMERecord}
+#    ::= {pilotObjectClass 15}
+#
+#
+#    domainRelatedObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            associatedDomain}
+#    ::= {pilotObjectClass 17}
+#
+#
+#    friendlyCountry OBJECT-CLASS
+#        SUBCLASS OF country
+#        MUST CONTAIN {
+#            friendlyCountryName}
+#    ::= {pilotObjectClass 18}
+#
+#
+#    simpleSecurityObject OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            userPassword }
+#    ::= {pilotObjectClass 19}
+#
+#
+#    pilotOrganization OBJECT-CLASS
+#        SUBCLASS OF organization, organizationalUnit
+#        MAY CONTAIN {
+#                    buildingName}
+#    ::= {pilotObjectClass 20}
+#
+#
+#    pilotDSA OBJECT-CLASS
+#        SUBCLASS OF dsa
+#        MUST CONTAIN {
+#            dSAQuality}
+#    ::= {pilotObjectClass 21}
+#
+#
+#    qualityLabelledData OBJECT-CLASS
+#        SUBCLASS OF top
+#        MUST CONTAIN {
+#            dSAQuality}
+#        MAY CONTAIN {
+#            subtreeMinimumQuality,
+#            subtreeMaximumQuality}
+#    ::= {pilotObjectClass 22}
+#
+#
+#
+#
+#    -- Standard Attribute Types
+#
+#    objectClass ObjectClass
+#        ::= {attributeType 0}
+#
+#
+#    aliasedObjectName AliasedObjectName
+#        ::= {attributeType 1}
+#
+#
+#    knowledgeInformation ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreString
+#        ::= {attributeType 2}
+#
+#
+#    commonName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-common-name))
+#        ::= {attributeType 3}
+#
+#
+#    surname ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-surname))
+#        ::= {attributeType 4}
+#
+#
+#    serialNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX printableStringSyntax
+#        (SIZE (1..ub-serial-number))
+#        ::= {attributeType 5}
+#
+#
+#    countryName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX PrintableString
+#        (SIZE (1..ub-country-code))
+#        SINGLE VALUE
+#        ::= {attributeType 6}
+#
+#
+#    localityName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-locality-name))
+#        ::= {attributeType 7}
+#
+#
+#    stateOrProvinceName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-state-name))
+#        ::= {attributeType 8}
+#
+#
+#    streetAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-street-address))
+#        ::= {attributeType 9}
+#
+#
+#    organizationName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-organization-name))
+#        ::= {attributeType 10}
+#
+#
+#    organizationalUnitName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-organizational-unit-name))
+#        ::= {attributeType 11}
+#
+#
+#    title ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-title))
+#        ::= {attributeType 12}
+#
+#
+#    description ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-description))
+#        ::= {attributeType 13}
+#
+#
+#    searchGuide ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX Guide
+#        ::= {attributeType 14}
+#
+#
+#    businessCategory ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-business-category))
+#        ::= {attributeType 15}
+#
+#
+#    postalAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX PostalAddress
+#        MATCHES FOR EQUALITY
+#        ::= {attributeType 16}
+#
+#
+#    postalCode ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-postal-code))
+#        ::= {attributeType 17}
+#
+#
+#    postOfficeBox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-post-office-box))
+#        ::= {attributeType 18}
+#
+#
+#    physicalDeliveryOfficeName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX caseIgnoreStringSyntax
+#        (SIZE (1..ub-physical-office-name))
+#        ::= {attributeType 19}
+#
+#
+#    telephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX telephoneNumberSyntax
+#        (SIZE (1..ub-telephone-number))
+#        ::= {attributeType 20}
+#
+#
+#    telexNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX TelexNumber
+#        (SIZE (1..ub-telex))
+#        ::= {attributeType 21}
+#
+#
+#    teletexTerminalIdentifier ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX TeletexTerminalIdentifier
+#        (SIZE (1..ub-teletex-terminal-id))
+#        ::= {attributeType 22}
+#
+#
+#    facsimileTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX FacsimileTelephoneNumber
+#        ::= {attributeType 23}
+#
+#
+#    x121Address ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX NumericString
+#        (SIZE (1..ub-x121-address))
+#        ::= {attributeType 24}
+#
+#
+#    internationaliSDNNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX NumericString
+#        (SIZE (1..ub-isdn-address))
+#        ::= {attributeType 25}
+#
+#
+#    registeredAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX PostalAddress
+#        ::= {attributeType 26}
+#
+#
+#    destinationIndicator ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX PrintableString
+#        (SIZE (1..ub-destination-indicator))
+#        MATCHES FOR EQUALITY SUBSTRINGS
+#        ::= {attributeType 27}
+#
+#
+#    preferredDeliveryMethod ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX deliveryMethod
+#        ::= {attributeType 28}
+#
+#
+#    presentationAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX PresentationAddress
+#        MATCHES FOR EQUALITY
+#        ::= {attributeType 29}
+#
+#
+#    supportedApplicationContext ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX objectIdentifierSyntax
+#        ::= {attributeType 30}
+#
+#
+#    member ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX distinguishedNameSyntax
+#        ::= {attributeType 31}
+#
+#
+#    owner ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX distinguishedNameSyntax
+#        ::= {attributeType 32}
+#
+#
+#    roleOccupant ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX distinguishedNameSyntax
+#        ::= {attributeType 33}
+#
+#
+#    seeAlso ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX distinguishedNameSyntax
+#        ::= {attributeType 34}
+#
+#
+#    userPassword ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX Userpassword
+#        ::= {attributeType 35}
+#
+#
+#    userCertificate ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX UserCertificate
+#        ::= {attributeType 36}
+#
+#
+#    cACertificate ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX cACertificate
+#        ::= {attributeType 37}
+#
+#
+#    authorityRevocationList ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX AuthorityRevocationList
+#        ::= {attributeType 38}
+#
+#
+#    certificateRevocationList ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX CertificateRevocationList
+#        ::= {attributeType 39}
+#
+#
+#    crossCertificatePair ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX CrossCertificatePair
+#        ::= {attributeType 40}
+#
+#
+#
+#
+#    -- Standard MHS Attribute Types
+#
+#    mhsDeliverableContentLength ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX integer
+#        ::= {mhsAttributeType 0}
+#
+#
+#    mhsDeliverableContentTypes ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oID
+#        ::= {mhsAttributeType 1}
+#
+#
+#    mhsDeliverableEits ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oID
+#        ::= {mhsAttributeType 2}
+#
+#
+#    mhsDLMembers ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oRName
+#        ::= {mhsAttributeType 3}
+#
+#
+#    mhsDLSubmitPermissions ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX dLSubmitPermission
+#        ::= {mhsAttributeType 4}
+#
+#
+#    mhsMessageStoreName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX dN
+#        ::= {mhsAttributeType 5}
+#
+#
+#    mhsORAddresses ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oRAddress
+#        ::= {mhsAttributeType 6}
+#
+#
+#    mhsPreferredDeliveryMethods ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX deliveryMethod
+#        ::= {mhsAttributeType 7}
+#
+#
+#    mhsSupportedAutomaticActions ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oID
+#        ::= {mhsAttributeType 8}
+#
+#
+#    mhsSupportedContentTypes ATTRIBUTE
+#
+#        WITH ATTRIBUTE-SYNTAX oID
+#        ::= {mhsAttributeType 9}
+#
+#
+#    mhsSupportedOptionalAttributes ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX oID
+#        ::= {mhsAttributeType 10}
+#
+#
+#
+#
+#    -- Pilot Attribute Types
+#
+#    userid ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-user-identifier))
+#    ::= {pilotAttributeType 1}
+#
+#
+#    textEncodedORAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#        (SIZE (1 .. ub-text-encoded-or-address))
+#    ::= {pilotAttributeType 2}
+#
+#
+#    rfc822Mailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            (SIZE (1 .. ub-rfc822-mailbox))
+#    ::= {pilotAttributeType 3}
+#
+#
+#    info ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-information))
+#    ::= {pilotAttributeType 4}
+#
+#
+#    favouriteDrink ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-favourite-drink))
+#    ::= {pilotAttributeType 5}
+#
+#
+#    roomNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-room-number))
+#    ::= {pilotAttributeType 6}
+#
+#
+#    photo ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            CHOICE {
+#                g3-facsimile [3] G3FacsimileBodyPart
+#                }
+#        (SIZE (1 .. ub-photo))
+#    ::= {pilotAttributeType 7}
+#
+#
+#    userClass ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-user-class))
+#    ::= {pilotAttributeType 8}
+#
+#
+#    host ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-host))
+#    ::= {pilotAttributeType 9}
+#
+#
+#    manager ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 10}
+#
+#
+#    documentIdentifier ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-identifier))
+#    ::= {pilotAttributeType 11}
+#
+#
+#    documentTitle ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#        (SIZE (1 .. ub-document-title))
+#    ::= {pilotAttributeType 12}
+#
+#
+#    documentVersion ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-version))
+#    ::= {pilotAttributeType 13}
+#
+#
+#    documentAuthor ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 14}
+#
+#
+#    documentLocation ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-document-location))
+#    ::= {pilotAttributeType 15}
+#
+#
+#    homeTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 20}
+#
+#
+#    secretary ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 21}
+#
+#
+#    otherMailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            SEQUENCE {
+#                    mailboxType PrintableString, -- e.g. Telemail
+#                    mailbox IA5String  -- e.g. X378:Joe
+#            }
+#    ::= {pilotAttributeType 22}
+#
+#
+#    lastModifiedTime ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            uTCTimeSyntax
+#    ::= {pilotAttributeType 23}
+#
+#
+#    lastModifiedBy ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 24}
+#
+#
+#    domainComponent ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            SINGLE VALUE
+#    ::= {pilotAttributeType 25}
+#
+#
+#    aRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 26}
+#
+#
+#    mXRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 28}
+#
+#
+#    nSRecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 29}
+#
+#    sOARecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            DNSRecordSyntax
+#    ::= {pilotAttributeType 30}
+#
+#
+#    cNAMERecord ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            iA5StringSyntax
+#    ::= {pilotAttributeType 31}
+#
+#
+#    associatedDomain ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#    ::= {pilotAttributeType 37}
+#
+#
+#    associatedName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 38}
+#
+#
+#    homePostalAddress ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            postalAddress
+#            MATCHES FOR EQUALITY
+#    ::= {pilotAttributeType 39}
+#
+#
+#    personalTitle ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-personal-title))
+#    ::= {pilotAttributeType 40}
+#
+#
+#    mobileTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 41}
+#
+#
+#    pagerTelephoneNumber ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            telephoneNumberSyntax
+#    ::= {pilotAttributeType 42}
+#
+#
+#    friendlyCountryName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#    ::= {pilotAttributeType 43}
+#
+#
+#    uniqueIdentifier ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-unique-identifier))
+#    ::= {pilotAttributeType 44}
+#
+#
+#    organizationalStatus ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-organizational-status))
+#    ::= {pilotAttributeType 45}
+#
+#
+#    janetMailbox ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreIA5StringSyntax
+#            (SIZE (1 .. ub-janet-mailbox))
+#    ::= {pilotAttributeType 46}
+#
+#
+#    mailPreferenceOption ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX ENUMERATED {
+#                no-list-inclusion(0),
+#                any-list-inclusion(1),  -- may be added to any lists
+#                professional-list-inclusion(2)
+#                                        -- may be added to lists
+#                                        -- which the list provider
+#                                        -- views as related to the
+#                                        -- users professional inter-
+#                                        -- ests, perhaps evaluated
+#                                        -- from the business of the
+#                                        -- organisation or keywords
+#                                        -- in the entry.
+#                }
+#    ::= {pilotAttributeType 47}
+#
+#
+#    buildingName ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            caseIgnoreStringSyntax
+#            (SIZE (1 .. ub-building-name))
+#    ::= {pilotAttributeType 48}
+#
+#
+#    dSAQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DSAQualitySyntax
+#            SINGLE VALUE
+#    ::= {pilotAttributeType 49}
+#
+#
+#    singleLevelQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#
+#
+#    subtreeMinimumQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#               -- Defaults to singleLevelQuality
+#    ::= {pilotAttributeType 51}
+#
+#
+#    subtreeMaximumQuality ATTRIBUTE
+#            WITH ATTRIBUTE-SYNTAX DataQualitySyntax
+#            SINGLE VALUE
+#               -- Defaults to singleLevelQuality
+#    ::= {pilotAttributeType 52}
+#
+#
+#    personalSignature ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            CHOICE {
+#                g3-facsimile [3] G3FacsimileBodyPart
+#                }
+#        (SIZE (1 .. ub-personal-signature))
+#    ::= {pilotAttributeType 53}
+#
+#
+#    dITRedirect ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            distinguishedNameSyntax
+#    ::= {pilotAttributeType 54}
+#
+#
+#    audio ATTRIBUTE
+#        WITH ATTRIBUTE-SYNTAX
+#            Audio
+#        (SIZE (1 .. ub-audio))
+#    ::= {pilotAttributeType 55}
+#
+#    documentPublisher ATTRIBUTE
+#            WITH ATTRIBUTE SYNTAX caseIgnoreStringSyntax
+#    ::= {pilotAttributeType 56}
+#
+#
+#
+#    -- Generally useful syntaxes
+#
+#
+#    caseIgnoreIA5StringSyntax ATTRIBUTE-SYNTAX
+#            IA5String
+#            MATCHES FOR EQUALITY SUBSTRINGS
+#
+#
+#    iA5StringSyntax ATTRIBUTE-SYNTAX
+#        IA5String
+#        MATCHES FOR EQUALITY SUBSTRINGS
+#
+#
+#    -- Syntaxes to support the DNS attributes
+#
+#    DNSRecordSyntax ATTRIBUTE-SYNTAX
+#            IA5String
+#            MATCHES FOR EQUALITY
+#
+#
+#    NRSInformationSyntax ATTRIBUTE-SYNTAX
+#            NRSInformation
+#            MATCHES FOR EQUALITY
+#
+#
+#    NRSInformation ::=  SET {
+#                    [0] Context,
+#                    [1] Address-space-id,
+#                    routes [2] SEQUENCE OF SEQUENCE {
+#                    Route-cost,
+#                    Addressing-info }
+#            }
+#
+#
+#    -- Upper bounds on length of attribute values
+#
+#
+#    ub-document-identifier INTEGER ::= 256
+#
+#    ub-document-location INTEGER ::= 256
+#
+#    ub-document-title INTEGER ::= 256
+#
+#    ub-document-version INTEGER ::= 256
+#
+#    ub-favourite-drink INTEGER ::= 256
+#
+#    ub-host INTEGER ::= 256
+#
+#    ub-information INTEGER ::= 2048
+#
+#    ub-unique-identifier INTEGER ::= 256
+#
+#    ub-personal-title INTEGER ::= 256
+#
+#    ub-photo INTEGER ::= 250000
+#
+#    ub-rfc822-mailbox INTEGER ::= 256
+#
+#    ub-room-number INTEGER ::= 256
+#
+#    ub-text-or-address INTEGER ::= 256
+#
+#    ub-user-class INTEGER ::= 256
+#
+#    ub-user-identifier INTEGER ::= 256
+#
+#    ub-organizational-status INTEGER ::= 256
+#
+#    ub-janet-mailbox INTEGER ::= 256
+#
+#    ub-building-name INTEGER ::= 256
+#
+#    ub-personal-signature ::= 50000
+#
+#    ub-audio INTEGER ::= 250000
+#
+# [remainder of memo trimmed]
+

Added: incubator/directory/eve/branches/start/src/schema/inetorgperson.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/inetorgperson.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,143 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/inetorgperson.schema,v 1.4.2.6 2001/10/09 17:15:08 kurt Exp $
+#
+# InetOrgPerson (RFC2798)
+#
+# Depends upon
+#   Definition of an X.500 Attribute Type and an Object Class to Hold
+#   Uniform Resource Identifiers (URIs) [RFC2079]
+#	(core.schema)
+#   
+#   A Summary of the X.500(96) User Schema for use with LDAPv3 [RFC2256]
+#	(core.schema)
+#
+#   The COSINE and Internet X.500 Schema [RFC1274] (cosine.schema)
+   
+# carLicense
+# This multivalued field is used to record the values of the license or
+# registration plate associated with an individual.
+attributetype ( 2.16.840.1.113730.3.1.1
+	NAME 'carLicense'
+	DESC 'RFC2798: vehicle license or registration plate'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# departmentNumber
+# Code for department to which a person belongs.  This can also be
+# strictly numeric (e.g., 1234) or alphanumeric (e.g., ABC/123).
+attributetype ( 2.16.840.1.113730.3.1.2
+	NAME 'departmentNumber'
+	DESC 'RFC2798: identifies a department within an organization'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# displayName
+# When displaying an entry, especially within a one-line summary list, it
+# is useful to be able to identify a name to be used.  Since other attri-
+# bute types such as 'cn' are multivalued, an additional attribute type is
+# needed.  Display name is defined for this purpose.
+attributetype ( 2.16.840.1.113730.3.1.241
+	NAME 'displayName'
+	DESC 'RFC2798: preferred name to be used when displaying entries'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# employeeNumber
+# Numeric or alphanumeric identifier assigned to a person, typically based
+# on order of hire or association with an organization.  Single valued.
+attributetype ( 2.16.840.1.113730.3.1.3
+	NAME 'employeeNumber'
+	DESC 'RFC2798: numerically identifies an employee within an organization'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# employeeType
+# Used to identify the employer to employee relationship.  Typical values
+# used will be "Contractor", "Employee", "Intern", "Temp", "External", and
+# "Unknown" but any value may be used.
+attributetype ( 2.16.840.1.113730.3.1.4
+	NAME 'employeeType'
+	DESC 'RFC2798: type of employment for a person'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# jpegPhoto
+# Used to store one or more images of a person using the JPEG File
+# Interchange Format [JFIF].
+# Note that the jpegPhoto attribute type was defined for use in the
+# Internet X.500 pilots but no referencable definition for it could be
+# located.    
+attributetype ( 0.9.2342.19200300.100.1.60
+	NAME 'jpegPhoto'
+	DESC 'a JPEG image'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )
+
+# preferredLanguage
+# Used to indicate an individual's preferred written or spoken
+# language.  This is useful for international correspondence or human-
+# computer interaction.  Values for this attribute type MUST conform to
+# the definition of the Accept-Language header field defined in
+# [RFC2068] with one exception:  the sequence "Accept-Language" ":"
+# should be omitted.  This is a single valued attribute type.
+attributetype ( 2.16.840.1.113730.3.1.39
+	NAME 'preferredLanguage'
+	DESC 'RFC2798: preferred written or spoken language for a person'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# userSMIMECertificate
+# A PKCS#7 [RFC2315] SignedData, where the content that is signed is
+# ignored by consumers of userSMIMECertificate values.  It is
+# recommended that values have a `contentType' of data with an absent
+# `content' field.  Values of this attribute contain a person's entire
+# certificate chain and an smimeCapabilities field [RFC2633] that at a
+# minimum describes their SMIME algorithm capabilities.  Values for
+# this attribute are to be stored and requested in binary form, as
+# 'userSMIMECertificate;binary'.  If available, this attribute is
+# preferred over the userCertificate attribute for S/MIME applications.
+## OpenLDAP note: ";binary" transfer should NOT be used as syntax is binary
+attributetype ( 2.16.840.1.113730.3.1.40
+	NAME 'userSMIMECertificate'
+	DESC 'RFC2798: PKCS#7 SignedData used to support S/MIME'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+# userPKCS12
+# PKCS #12 [PKCS12] provides a format for exchange of personal identity
+# information.  When such information is stored in a directory service,
+# the userPKCS12 attribute should be used. This attribute is to be stored
+# and requested in binary form, as 'userPKCS12;binary'.  The attribute
+# values are PFX PDUs stored as binary data.
+## OpenLDAP note: ";binary" transfer should NOT be used as syntax is binary
+attributetype ( 2.16.840.1.113730.3.1.216
+	NAME 'userPKCS12'
+	DESC 'RFC2798: PKCS #12 PFX PDU for exchange of 
+		personal identity information'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+
+# inetOrgPerson
+# The inetOrgPerson represents people who are associated with an
+# organization in some way.  It is a structural class and is derived
+# from the organizationalPerson which is defined in X.521 [X521].
+objectclass	( 2.16.840.1.113730.3.2.2
+    NAME 'inetOrgPerson'
+	DESC 'RFC2798: Internet Organizational Person'
+    SUP organizationalPerson
+    STRUCTURAL
+	MAY (
+		audio $ businessCategory $ carLicense $ departmentNumber $
+		displayName $ employeeNumber $ employeeType $ givenName $
+		homePhone $ homePostalAddress $ initials $ jpegPhoto $
+		labeledURI $ mail $ manager $ mobile $ o $ pager $
+		photo $ roomNumber $ secretary $ uid $ userCertificate $
+		x500uniqueIdentifier $ preferredLanguage $
+		userSMIMECertificate $ userPKCS12 )
+	)  

Added: incubator/directory/eve/branches/start/src/schema/java.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/java.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,388 @@
+# Java Object Schema
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/java.schema,v 1.1.2.2 2000/09/13 18:16:13 kurt Exp $
+# depends upon core.schema
+
+# Network Working Group                                            V. Ryan
+# Request for Comments: 2713                                   S. Seligman
+# Category: Informational                                           R. Lee
+#                                                   Sun Microsystems, Inc.
+#                                                             October 1999
+# 
+# 
+#      Schema for Representing Java(tm) Objects in an LDAP Directory
+# 
+# Status of this Memo
+# 
+#    This memo provides information for the Internet community.  It does
+#    not specify an Internet standard of any kind.  Distribution of this
+#    memo is unlimited.
+# 
+# Copyright Notice
+# 
+#    Copyright (C) The Internet Society (1999).  All Rights Reserved.
+# 
+# Abstract
+# 
+#    This document defines the schema for representing Java(tm) objects in
+#    an LDAP directory [LDAPv3].  It defines schema elements to represent
+#    a Java serialized object [Serial], a Java marshalled object [RMI], a
+#    Java remote object [RMI], and a JNDI reference [JNDI].
+# 
+
+# [trimmed]
+
+# 3 Attribute Type Definitions
+# 
+#    The following attribute types are defined in this document:
+# 
+#        javaClassName
+#        javaClassNames
+#        javaCodebase
+#        javaSerializedData
+#        javaFactory
+#        javaReferenceAddress
+#        javaDoc
+# 
+# 3.1 javaClassName
+# 
+#    This attribute stores the fully qualified name of the Java object's
+#    "distinguished" class or interface (for example, "java.lang.String").
+#    It is a single-valued attribute. This attribute's syntax is '
+#    Directory String' and its case is significant.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.6
+#          NAME 'javaClassName'
+#          DESC 'Fully qualified name of distinguished Java class or
+#                interface'
+#          EQUALITY caseExactMatch
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+#          SINGLE-VALUE
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.6
+	NAME 'javaClassName'
+	DESC 'Fully qualified name of distinguished Java class or interface'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+ 
+# 3.2 javaCodebase
+# 
+#    This attribute stores the Java class definition's locations.  It
+#    specifies the locations from which to load the class definition for
+#    the class specified by the javaClassName attribute.  Each value of
+#    the attribute contains an ordered list of URLs, separated by spaces.
+#    For example, a value of "url1 url2 url3" means that the three
+#    (possibly interdependent) URLs (url1, url2, and url3) form the
+#    codebase for loading in the Java class definition.
+# 
+#    If the javaCodebase attribute contains more than one value, each
+#    value is an independent codebase. That is, there is no relationship
+#    between the URLs in one value and those in another; each value can be
+#    viewed as an alternate source for loading the Java class definition.
+#    See [Java] for information regarding class loading.
+# 
+#    This attribute's syntax is 'IA5 String' and its case is significant.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.7
+#          NAME 'javaCodebase'
+#          DESC 'URL(s) specifying the location of class definition'
+#          EQUALITY caseExactIA5Match
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.7
+	NAME 'javaCodebase'
+	DESC 'URL(s) specifying the location of class definition'
+	EQUALITY caseExactIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 3.3 javaClassNames
+# 
+#    This attribute stores the Java object's fully qualified class or
+#    interface names (for example, "java.lang.String").  It is a
+#    multivalued attribute. When more than one value is present, each is
+#    the name of a class or interface, or ancestor class or interface, of
+#    this object.
+# 
+#    This attribute's syntax is 'Directory String' and its case is
+#    significant.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.13
+#          NAME 'javaClassNames'
+#          DESC 'Fully qualified Java class or interface name'
+#          EQUALITY caseExactMatch
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+#        )
+# 
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.13
+	NAME 'javaClassNames'
+	DESC 'Fully qualified Java class or interface name'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+ 
+# 3.4 javaSerializedData
+# 
+#    This attribute stores the serialized form of a Java object.  The
+#    serialized form is described in [Serial].
+# 
+#    This attribute's syntax is 'Octet String'.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.8
+#          NAME 'javaSerializedData
+#          DESC 'Serialized form of a Java object'
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+#          SINGLE-VALUE
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.8
+	NAME 'javaSerializedData'
+	DESC 'Serialized form of a Java object'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+	SINGLE-VALUE )
+
+# 3.5 javaFactory
+# 
+#    This attribute stores the fully qualified class name of the object
+#    factory (for example, "com.wiz.jndi.WizObjectFactory") that can be
+#    used to create an instance of the object identified by the
+#    javaClassName attribute.
+# 
+#    This attribute's syntax is 'Directory String' and its case is
+#    significant.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.10
+#          NAME 'javaFactory'
+#          DESC 'Fully qualified Java class name of a JNDI object factory'
+#          EQUALITY caseExactMatch
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+#          SINGLE-VALUE
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.10
+	NAME 'javaFactory'
+	DESC 'Fully qualified Java class name of a JNDI object factory'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# 3.6 javaReferenceAddress
+# 
+#    This attribute represents the sequence of addresses of a JNDI
+#    reference.  Each of its values represents one address, a Java object
+#    of type javax.naming.RefAddr.  Its value is a concatenation of the
+#    address type and address contents, preceded by a sequence number (the
+#    order of addresses in a JNDI reference is significant).  For example:
+# 
+#        #0#TypeA#ValA
+#        #1#TypeB#ValB
+#        #2#TypeC##rO0ABXNyABpq...
+# 
+#    In more detail, the value is encoded as follows:
+# 
+#    The delimiter is the first character of the value.  For readability
+#    the character '#' is recommended when it is not otherwise used
+#    anywhere in the value, but any character may be used subject to
+#    restrictions given below.
+# 
+#    The first delimiter is followed by the sequence number.  The sequence
+#    number of an address is its position in the JNDI reference, with the
+#    first address being numbered 0.  It is represented by its shortest
+#    string form, in decimal notation.
+# 
+#    The sequence number is followed by a delimiter, then by the address
+#    type, and then by another delimiter.  If the address is of Java class
+#    javax.naming.StringRefAddr, then this delimiter is followed by the
+#    value of the address contents (which is a string).  Otherwise, this
+#    delimiter is followed immediately by another delimiter, and then by
+#    the Base64 encoding of the serialized form of the entire address.
+# 
+#    The delimiter may be any character other than a digit or a character
+#    contained in the address type.  In addition, if the address contents
+#    is a string, the delimiter may not be the first character of that
+#    string.
+# 
+#    This attribute's syntax is 'Directory String' and its case is
+#    significant.  It can contain multiple values.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.11
+#          NAME 'javaReferenceAddress'
+#          DESC 'Addresses associated with a JNDI Reference'
+#          EQUALITY caseExactMatch
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.11
+	NAME 'javaReferenceAddress'
+	DESC 'Addresses associated with a JNDI Reference'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# 3.7 javaDoc
+# 
+#    This attribute stores a pointer to the Java documentation for the
+#    class.  It's value is a URL. For example, the following URL points to
+#    the specification of the java.lang.String class:
+#    http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html
+# 
+#    This attribute's syntax is 'IA5 String' and its case is significant.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.1.12
+#          NAME 'javaDoc'
+#          DESC 'The Java documentation for the class'
+#          EQUALITY caseExactIA5Match
+#          SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+#        )
+# 
+attributetype ( 1.3.6.1.4.1.42.2.27.4.1.12
+	NAME 'javaDoc'
+	DESC 'The Java documentation for the class'
+	EQUALITY caseExactIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 4 Object Class Definitions
+# 
+#    The following object classes are defined in this document:
+# 
+#        javaContainer
+#        javaObject
+#        javaSerializedObject
+#        javaMarshalledObject
+#        javaNamingReference
+# 
+# 4.1 javaContainer
+# 
+#    This structural object class represents a container for a Java
+#    object.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.2.1
+#          NAME 'javaContainer'
+#          DESC 'Container for a Java object'
+#          SUP top
+#          STRUCTURAL
+#          MUST ( cn )
+#        )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.1
+	NAME 'javaContainer'
+	DESC 'Container for a Java object'
+	SUP top
+	STRUCTURAL
+	MUST cn )
+
+# 4.2 javaObject
+# 
+#    This abstract object class represents a Java object.  A javaObject
+#    cannot exist in the directory; only auxiliary or structural
+#    subclasses of it can exist in the directory.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.2.4
+#          NAME 'javaObject'
+#          DESC 'Java object representation'
+#          SUP top
+#          ABSTRACT
+#          MUST ( javaClassName )
+#          MAY ( javaClassNames $
+#                javaCodebase $
+#                javaDoc $
+#                description )
+#        )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.4
+	NAME 'javaObject'
+	DESC 'Java object representation'
+	SUP top
+	ABSTRACT
+	MUST javaClassName
+	MAY ( javaClassNames $ javaCodebase $
+		javaDoc $ description ) )
+
+# 4.3 javaSerializedObject
+# 
+#    This auxiliary object class represents a Java serialized object.  It
+#    must be mixed in with a structural object class.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.2.5
+#          NAME 'javaSerializedObject'
+#          DESC 'Java serialized object'
+#          SUP javaObject
+#          AUXILIARY
+#          MUST ( javaSerializedData )
+#        )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.5
+	NAME 'javaSerializedObject'
+	DESC 'Java serialized object'
+	SUP javaObject
+	AUXILIARY
+	MUST javaSerializedData )
+ 
+# 4.4 javaMarshalledObject
+# 
+#    This auxiliary object class represents a Java marshalled object.  It
+#    must be mixed in with a structural object class.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.2.8
+#          NAME 'javaMarshalledObject'
+#          DESC 'Java marshalled object'
+#          SUP javaObject
+#          AUXILIARY
+#          MUST ( javaSerializedData )
+#        )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.8
+	NAME 'javaMarshalledObject'
+	DESC 'Java marshalled object'
+	SUP javaObject
+	AUXILIARY
+	MUST javaSerializedData )
+
+# 4.5 javaNamingReference
+# 
+#    This auxiliary object class represents a JNDI reference.  It must be
+#    mixed in with a structural object class.
+# 
+#        ( 1.3.6.1.4.1.42.2.27.4.2.7
+#          NAME 'javaNamingReference'
+#          DESC 'JNDI reference'
+#          SUP javaObject
+#          AUXILIARY
+#          MAY ( javaReferenceAddress $
+#                javaFactory )
+#        )
+# 
+objectclass ( 1.3.6.1.4.1.42.2.27.4.2.7
+	NAME 'javaNamingReference'
+	DESC 'JNDI reference'
+	SUP javaObject
+	AUXILIARY
+	MAY ( javaReferenceAddress $ javaFactory ) )
+ 
+# Full Copyright Statement
+# 
+#    Copyright (C) The Internet Society (1999).  All Rights Reserved.
+# 
+#    This document and translations of it may be copied and furnished to
+#    others, and derivative works that comment on or otherwise explain it
+#    or assist in its implementation may be prepared, copied, published
+#    and distributed, in whole or in part, without restriction of any
+#    kind, provided that the above copyright notice and this paragraph are
+#    included on all such copies and derivative works.  However, this
+#    document itself may not be modified in any way, such as by removing
+#    the copyright notice or references to the Internet Society or other
+#    Internet organizations, except as needed for the purpose of
+#    developing Internet standards in which case the procedures for
+#    copyrights defined in the Internet Standards process must be
+#    followed, or as required to translate it into languages other than
+#    English.
+# 
+#    The limited permissions granted above are perpetual and will not be
+#    revoked by the Internet Society or its successors or assigns.
+# 
+#    This document and the information contained herein is provided on an
+#    "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+#    TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+#    BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+#    HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+#    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Added: incubator/directory/eve/branches/start/src/schema/krb5-kdc.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/krb5-kdc.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,134 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/krb5-kdc.schema,v 1.1.2.1 2000/09/05 18:28:34 kurt Exp $
+# $Id: krb5-kdc.schema,v 1.2 2002/12/14 01:30:10 akarasulu Exp $
+# Definitions for a Kerberos V KDC schema
+
+# OID Base is iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) padl(5322) kdcSchema(10)
+#
+# Syntaxes are under 1.3.6.1.4.1.5322.10.0
+# Attributes types are under 1.3.6.1.4.1.5322.10.1
+# Object classes are under 1.3.6.1.4.1.5322.10.2
+
+# Syntax definitions
+
+#krb5KDCFlagsSyntax SYNTAX ::= {
+#   WITH SYNTAX            INTEGER
+#--        initial(0),             -- require as-req
+#--        forwardable(1),         -- may issue forwardable
+#--        proxiable(2),           -- may issue proxiable
+#--        renewable(3),           -- may issue renewable
+#--        postdate(4),            -- may issue postdatable
+#--        server(5),              -- may be server
+#--        client(6),              -- may be client
+#--        invalid(7),             -- entry is invalid
+#--        require-preauth(8),     -- must use preauth
+#--        change-pw(9),           -- change password service
+#--        require-hwauth(10),     -- must use hwauth
+#--        ok-as-delegate(11),     -- as in TicketFlags
+#--        user-to-user(12),       -- may use user-to-user auth
+#--        immutable(13)           -- may not be deleted         
+#   ID                     { 1.3.6.1.4.1.5322.10.0.1 }
+#}
+
+#krb5PrincipalNameSyntax SYNTAX ::= {
+#   WITH SYNTAX            OCTET STRING
+#-- String representations of distinguished names as per RFC1510
+#   ID                     { 1.3.6.1.4.1.5322.10.0.2 }
+#}
+
+# Attribute type definitions
+ 
+attributetype ( 1.3.6.1.4.1.5322.10.1.1
+	NAME 'krb5PrincipalName'
+	DESC 'The unparsed Kerberos principal name'
+	EQUALITY caseExactIA5Match
+	SINGLE-VALUE
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.2
+	NAME 'krb5KeyVersionNumber'
+	EQUALITY integerMatch
+	SINGLE-VALUE
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.3
+	NAME 'krb5MaxLife'
+	EQUALITY integerMatch
+	SINGLE-VALUE
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.4
+	NAME 'krb5MaxRenew'
+	EQUALITY integerMatch
+	SINGLE-VALUE
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.5
+	NAME 'krb5KDCFlags'
+	EQUALITY integerMatch
+	SINGLE-VALUE
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.6
+	NAME 'krb5EncryptionType'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.7
+	NAME 'krb5ValidStart'
+	ORDERING generalizedTimeOrderingMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+	SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.8
+	NAME 'krb5ValidEnd'
+	ORDERING generalizedTimeOrderingMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+	SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.9
+	NAME 'krb5PasswordEnd'
+	ORDERING generalizedTimeOrderingMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+	SINGLE-VALUE )
+
+# this is temporary; keys will eventually
+# be child entries or compound attributes.
+attributetype ( 1.3.6.1.4.1.5322.10.1.10
+	NAME 'krb5Key'
+	DESC 'Encoded ASN1 Key as an octet string'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.11
+	NAME 'krb5PrincipalRealm'
+	DESC 'Distinguished name of krb5Realm entry'
+	SUP distinguishedName )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.12
+	NAME 'krb5RealmName'
+	EQUALITY octetStringMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Object class definitions
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.1
+	NAME 'krb5Principal'
+	SUP top
+	AUXILIARY
+	MUST ( krb5PrincipalName )
+	MAY ( cn $ krb5PrincipalRealm ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.2
+	NAME 'krb5KDCEntry'
+	SUP krb5Principal
+	AUXILIARY
+	MUST ( krb5KeyVersionNumber )
+	MAY ( krb5ValidStart $ krb5ValidEnd $ krb5PasswordEnd $
+              krb5MaxLife $ krb5MaxRenew $ krb5KDCFlags $
+              krb5EncryptionType $ krb5Key ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.3
+	NAME 'krb5Realm'
+	SUP top
+	AUXILIARY
+	MUST ( krb5RealmName ) )
+

Added: incubator/directory/eve/branches/start/src/schema/misc.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/misc.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,66 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/misc.schema,v 1.2.8.11 2002/01/08 20:19:06 kurt Exp $
+#
+# Assorted definitions from several sources, including
+# ''works in progress''.  Contents of this file are
+# subject to change (including deletion) without notice.
+#
+# Not recommended for production use!
+# Use with extreme caution!
+
+#
+# draft-lachman-laser-ldap-mail-routing-02.txt !!!EXPIRED!!!
+#
+attributetype ( 2.16.840.1.113730.3.1.13
+	NAME 'mailLocalAddress'
+	DESC 'RFC822 email address of this recipient'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+attributetype ( 2.16.840.1.113730.3.1.18
+	NAME 'mailHost'
+	DESC 'FQDN of the SMTP/MTA of this recipient'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
+	SINGLE-VALUE )
+
+attributetype ( 2.16.840.1.113730.3.1.47
+	NAME 'mailRoutingAddress'
+	DESC 'RFC822 routing address of this recipient'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
+	SINGLE-VALUE )
+
+# OID needs to be determined
+#objectclass ( 2.16.840.1.113730.3.2.TBD
+#	NAME 'inetLocalMailRecipient'
+#	DESC 'Internet local mail recipient'
+#	SUP top AUXILIARY
+#	MAY	( mailLocalAddress $ mailHost $ mailRoutingAddress ) )
+
+# I-D leaves this OID TBD.
+# iPlanet uses 2.16.840.1.113.730.3.2.147 but that appears to be
+# an improperly delegated OID.  A typo is suspected.
+objectclass ( 2.16.840.1.113730.3.2.147
+	NAME 'inetLocalMailRecipient'
+	DESC 'Internet local mail recipient'
+	SUP top AUXILIARY
+	MAY	( mailLocalAddress $ mailHost $ mailRoutingAddress ) )
+
+#
+# draft-srivastava-ldap-mail-00.txt !!!EXPIRED!!!
+#
+attributetype ( 1.3.6.1.4.1.42.2.27.2.1.15
+	NAME 'rfc822MailMember'
+	DESC 'rfc822 mail address of group member(s)'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# 
+# !!!no I-D!!!
+#
+objectclass ( 1.3.6.1.4.1.42.2.27.1.2.5
+	NAME 'nisMailAlias'
+	DESC 'NIS mail alias'
+	SUP top STRUCTURAL
+	MUST cn
+	MAY rfc822MailMember )

Added: incubator/directory/eve/branches/start/src/schema/nis.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/nis.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,224 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/nis.schema,v 1.1.8.5 2000/09/28 17:35:12 kurt Exp $
+# Definitions from RFC2307 (Experimental)
+#	An Approach for Using LDAP as a Network Information Service
+
+# Depends upon core.schema and cosine.schema
+
+# Note: The definitions in RFC2307 are given in syntaxes closely related
+# to those in RFC2252, however, some liberties are taken that are not
+# supported by RFC2252.  This file has been written following RFC2252
+# strictly.
+
+# OID Base is iso(1) org(3) dod(6) internet(1) directory(1) nisSchema(1).
+# i.e. nisSchema in RFC2307 is 1.3.6.1.1.1
+#
+# Syntaxes are under 1.3.6.1.1.1.0 (two new syntaxes are defined)
+#	validaters for these syntaxes are incomplete, they only
+#	implement printable string validation (which is good as the
+#	common use of these syntaxes violates the specification).
+# Attribute types are under 1.3.6.1.1.1.1
+# Object classes are under 1.3.6.1.1.1.2
+
+# Attribute Type Definitions
+
+attributetype ( 1.3.6.1.1.1.1.0 NAME 'uidNumber'
+	DESC 'An integer uniquely identifying a user in an administrative domain'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.1 NAME 'gidNumber'
+	DESC 'An integer uniquely identifying a group in an administrative domain'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.2 NAME 'gecos'
+	DESC 'The GECOS field; the common name'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.3 NAME 'homeDirectory'
+	DESC 'The absolute path to the home directory'
+	EQUALITY caseExactIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.4 NAME 'loginShell'
+	DESC 'The path to the login shell'
+	EQUALITY caseExactIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.5 NAME 'shadowLastChange'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.6 NAME 'shadowMin'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.7 NAME 'shadowMax'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.8 NAME 'shadowWarning'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.9 NAME 'shadowInactive'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.10 NAME 'shadowExpire'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.11 NAME 'shadowFlag'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.12 NAME 'memberUid'
+	EQUALITY caseExactIA5Match
+	SUBSTR caseExactIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.1.1.1.13 NAME 'memberNisNetgroup'
+	EQUALITY caseExactIA5Match
+	SUBSTR caseExactIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
+	DESC 'Netgroup triple'
+	SYNTAX 1.3.6.1.1.1.0.0 )
+
+attributetype ( 1.3.6.1.1.1.1.15 NAME 'ipServicePort'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.16 NAME 'ipServiceProtocol'
+	SUP name )
+
+attributetype ( 1.3.6.1.1.1.1.17 NAME 'ipProtocolNumber'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.18 NAME 'oncRpcNumber'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.19 NAME 'ipHostNumber'
+	DESC 'IP address as a dotted decimal, eg. 192.168.1.1, omitting leading zeros'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+
+attributetype ( 1.3.6.1.1.1.1.20 NAME 'ipNetworkNumber'
+	DESC 'IP network as a dotted decimal, eg. 192.168, omitting leading zeros'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.21 NAME 'ipNetmaskNumber'
+	DESC 'IP netmask as a dotted decimal, eg. 255.255.255.0, omitting leading zeros'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.1.1.1.22 NAME 'macAddress'
+	DESC 'MAC address in maximal, colon separated hex notation, eg. 00:00:92:90:ee:e2'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+
+attributetype ( 1.3.6.1.1.1.1.23 NAME 'bootParameter'
+	DESC 'rpc.bootparamd parameter'
+	SYNTAX 1.3.6.1.1.1.0.1 )
+
+attributetype ( 1.3.6.1.1.1.1.24 NAME 'bootFile'
+	DESC 'Boot image name'
+	EQUALITY caseExactIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.1.1.1.26 NAME 'nisMapName'
+	SUP name )
+
+attributetype ( 1.3.6.1.1.1.1.27 NAME 'nisMapEntry'
+	EQUALITY caseExactIA5Match
+	SUBSTR caseExactIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{1024} SINGLE-VALUE )
+
+# Object Class Definitions
+
+objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY
+	DESC 'Abstraction of an account with POSIX attributes'
+	MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
+	MAY ( userPassword $ loginShell $ gecos $ description ) )
+
+objectclass ( 1.3.6.1.1.1.2.1 NAME 'shadowAccount' SUP top AUXILIARY
+	DESC 'Additional attributes for shadow passwords'
+	MUST uid
+	MAY ( userPassword $ shadowLastChange $ shadowMin $
+	      shadowMax $ shadowWarning $ shadowInactive $
+	      shadowExpire $ shadowFlag $ description ) )
+
+objectclass ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' SUP top STRUCTURAL
+	DESC 'Abstraction of a group of accounts'
+	MUST ( cn $ gidNumber )
+	MAY ( userPassword $ memberUid $ description ) )
+
+objectclass ( 1.3.6.1.1.1.2.3 NAME 'ipService' SUP top STRUCTURAL
+	DESC 'Abstraction an Internet Protocol service.
+	      Maps an IP port and protocol (such as tcp or udp)
+	      to one or more names; the distinguished value of
+	      the cn attribute denotes the service"s canonical
+	      name'
+	MUST ( cn $ ipServicePort $ ipServiceProtocol )
+	MAY ( description ) )
+
+objectclass ( 1.3.6.1.1.1.2.4 NAME 'ipProtocol' SUP top STRUCTURAL
+	DESC 'Abstraction of an IP protocol. Maps a protocol number
+	      to one or more names. The distinguished value of the cn
+	      attribute denotes the protocol"s canonical name'
+	MUST ( cn $ ipProtocolNumber $ description )
+	MAY description )
+
+objectclass ( 1.3.6.1.1.1.2.5 NAME 'oncRpc' SUP top STRUCTURAL
+	DESC 'Abstraction of an Open Network Computing (ONC)
+	      [RFC1057] Remote Procedure Call (RPC) binding.
+	      This class maps an ONC RPC number to a name.
+	      The distinguished value of the cn attribute denotes
+	      the RPC service"s canonical name'
+	MUST ( cn $ oncRpcNumber $ description )
+	MAY description )
+
+objectclass ( 1.3.6.1.1.1.2.6 NAME 'ipHost' SUP top AUXILIARY
+	DESC 'Abstraction of a host, an IP device. The distinguished
+	      value of the cn attribute denotes the host"s canonical
+	      name. Device SHOULD be used as a structural class'
+	MUST ( cn $ ipHostNumber )
+	MAY ( l $ description $ manager ) )
+
+objectclass ( 1.3.6.1.1.1.2.7 NAME 'ipNetwork' SUP top STRUCTURAL
+	DESC 'Abstraction of a network. The distinguished value of
+	      the cn attribute denotes the network"s canonical name'
+	MUST ( cn $ ipNetworkNumber )
+	MAY ( ipNetmaskNumber $ l $ description $ manager ) )
+
+objectclass ( 1.3.6.1.1.1.2.8 NAME 'nisNetgroup' SUP top STRUCTURAL
+	DESC 'Abstraction of a netgroup. May refer to other netgroups'
+	MUST cn
+	MAY ( nisNetgroupTriple $ memberNisNetgroup $ description ) )
+
+objectclass ( 1.3.6.1.1.1.2.9 NAME 'nisMap' SUP top STRUCTURAL
+	DESC 'A generic abstraction of a NIS map'
+	MUST nisMapName
+	MAY description )
+
+objectclass ( 1.3.6.1.1.1.2.10 NAME 'nisObject' SUP top STRUCTURAL
+	DESC 'An entry in a NIS map'
+	MUST ( cn $ nisMapEntry $ nisMapName )
+	MAY description )
+
+objectclass ( 1.3.6.1.1.1.2.11 NAME 'ieee802Device' SUP top AUXILIARY
+	DESC 'A device with a MAC address; device SHOULD be
+	      used as a structural class'
+	MAY macAddress )
+
+objectclass ( 1.3.6.1.1.1.2.12 NAME 'bootableDevice' SUP top AUXILIARY
+	DESC 'A device with boot parameters; device SHOULD be
+	      used as a structural class'
+	MAY ( bootFile $ bootParameter ) )

Added: incubator/directory/eve/branches/start/src/schema/openldap.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/openldap.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,31 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/openldap.schema,v 1.10.2.6 2000/10/11 02:36:50 kurt Exp $
+#
+# OpenLDAP Project's directory schema items
+#
+# depends upon:
+#	core.schema
+#	cosine.schema
+#	inetorgperson.schema
+#
+# These are provided for informational purposes only.
+
+objectclass ( 1.3.6.1.4.1.4203.1.4.3 NAME 'OpenLDAPorg'
+	DESC 'OpenLDAP Organizational Object'
+	SUP organization
+	MAY ( buildingName $ displayName $ labeledURI ) )
+
+objectclass ( 1.3.6.1.4.1.4203.1.4.4 NAME 'OpenLDAPou'
+	DESC 'OpenLDAP Organizational Unit Object'
+	SUP organizationalUnit
+	MAY ( buildingName $ displayName $ labeledURI $ o ) )
+
+objectclass ( 1.3.6.1.4.1.4203.1.4.5 NAME 'OpenLDAPperson'
+	DESC 'OpenLDAP Person'
+	SUP ( pilotPerson $ inetOrgPerson )
+	MUST ( uid $ cn )
+	MAY ( givenName $ labeledURI $ o ) )
+
+objectclass ( 1.3.6.1.4.1.4203.1.4.6 NAME 'OpenLDAPdisplayableObject'
+	DESC 'OpenLDAP Displayable Object'
+	MAY displayName AUXILIARY )
+

Added: incubator/directory/eve/branches/start/src/schema/our.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/our.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,27 @@
+#
+# Internal operational attributes used by our server.  We do not have valid OIDs 
+# for these datatypes so we made them up.  This really is a bad idea.  But its 
+# a temp fix.
+#
+
+attributetype ( 2.5.18.12.5.18.12.5.18.1 NAME 'parentId'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.12.5.18.12.5.18.2 NAME 'entryId'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.12.5.18.12.5.18.3 NAME 'numSubordinates'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attributetype ( 2.5.18.12.5.18.12.5.18.4 NAME 'parentDn'
+	EQUALITY distinguishedNameMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+

Added: incubator/directory/eve/branches/start/src/schema/vendor.schema
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/src/schema/vendor.schema	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,41 @@
+#
+# Storing Vendor Information in the LDAP root DSE
+# http://www.faqs.org/rfcs/rfc3045.html
+#
+
+
+
+# 2.1 vendorName
+#
+#   This attribute contains a single string, which represents the name of
+#   the LDAP server implementer.
+#
+#   All LDAP server implementations SHOULD maintain a vendorName, which
+#   is generally the name of the company that wrote the LDAP Server code
+#   like "Novell, Inc."
+
+attributetype ( 1.3.6.1.1.4 NAME 'vendorName' 
+	EQUALITY caseExactIA5Match 
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
+
+
+# 2.2 vendorVersion
+#   This attribute contains a string which represents the version of the
+#   LDAP server implementation.
+#
+#   All LDAP server implementations SHOULD maintain a vendorVersion.
+#   Note that this value is typically a release value--comprised of a
+#   string and/or a string of numbers--used by the developer of the LDAP
+#   server product (as opposed to the supportedLDAPVersion, which
+#   specifies the version of the LDAP protocol supported by this server).
+#   This is single-valued so that it will only have one version value.
+#   This string MUST be unique between two versions, but there are no
+#   other syntactic restrictions on the value or the way it is formatted.
+
+attributetype ( 1.3.6.1.1.5 NAME 'vendorVersion' 
+	EQUALITY caseExactIA5Match 
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+    SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )
+
+

Added: incubator/directory/eve/branches/start/todo.txt
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/todo.txt	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,4 @@
+ o add check to build.xml for proper ant version
+ o test it out
+ o add modified phoenix download and install option to build
+

Added: incubator/directory/eve/branches/start/xdocs/design/operations/index.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/design/operations/index.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<document>
+	<body>
+		<section name="LDAP Operations">
+			<p>Currently no content for this page.</p>
+		</section>
+	</body>
+</document>

Added: incubator/directory/eve/branches/start/xdocs/design/operations/navigation.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/design/operations/navigation.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<project name="LDAPd">
+	<title>Home</title>
+	<body>
+		<links>
+			<item name="LDAPd" href="http://ldapd.sourceforge.net"/>
+		</links>
+		<menu name="Overview">
+			<item name="Home" href="http://ldapd.sourceforge.net"/>
+		</menu>
+		<menu name="Design Documentation">
+				<item name="Authentication" href="/authentication-module.html"/>
+				<item name="Backend" href="/../../backend-module.html"/>
+				<item name="Client" href="/../../client-module.html"/>
+				<item name="Decoder" href="/../../decoder-module.html"/>
+				<item name="Encoder" href="/../../encoder-module.html"/>
+				<item name="Event" href="/../../event-module.html"/>
+				<item name="Input" href="/../../input-module.html"/>
+				<item name="JNDI Provider" href="/../../jndi-provider-module.html"/>
+				<item name="Listener" href="/../../listener-module.html"/>
+				<item name="Nexus" href="/../../nexus-module.html"/>
+				<item name="Output" href="/../../output-module.html"/>
+				<item name="Protocol" href="/../../protocol-module.html"/>
+				<item name="RootDSE" href="/../../rootdse-/design.html"/>
+				<item name="Schema" href="/../../schema-module.html"/>
+				<item name="SEDA" href="/../../seda-implementation.html"/>
+				<item name="Server Architecture" href="/../../server-architecture.html"/>
+				<item name="Triggers and Procedures" href="/../../triggers-and-procedures.html"/>
+				<item/>
+				<item name="Operations" href="/design/operations/index.html">
+					<item name="Search" href="/design/operations/search-operation.html"/>
+				</item>
+		</menu>
+		<menu name="Other Modules">
+			<item name="Common" href="/../../../module-blank.html"/>
+			<item name="Replication" href="/../../../module-blank.html"/>
+		</menu>
+		<menu name="Backends">
+			<item name="Berkeley" href="/../../../backend-blank.html"/>
+			<item name="JDBC" href="/../../../backend-blank.html"/>
+			<item name="JDBM" href="/../../../backend-blank.html"/>
+		</menu>
+	</body>
+</project>

Added: incubator/directory/eve/branches/start/xdocs/devprocess.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/devprocess.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<document>
+</document>

Added: incubator/directory/eve/branches/start/xdocs/index.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/index.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <author email="bearcej at users.sourceforge.net">Jim Bearce</author>
+        <title>LDAPd</title>
+    </properties>
+    <body>
+        <section name="Server Documentation">
+            <p>This subproject consists of the core server code which makes up the heart
+            of the LDAPd project.</p>
+            <p>The parts of the server are documented in the following pages.</p>
+        </section>
+    </body>
+</document>

Added: incubator/directory/eve/branches/start/xdocs/navigation.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/navigation.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<project name="LDAPd">
+    <title>Home</title>
+    <body>
+        <links>
+            <item name="Avalon" href="http://avalon.apache.org"/>
+            <item name="Phoenix" href="http://avalon.apache.org/phoenix"/>
+        </links>
+        <menu name="Overview">
+            <item name="Home" href="/../../"/>
+        </menu>
+        <menu name="Design Documentation">
+                <item name="Authentication" href="/design/authentication-module.html"/>
+                <item name="Backend" href="/design/backend-module.html"/>
+                <item name="Client" href="/design/client-module.html"/>
+                <item name="Decoder" href="/design/decoder-module.html"/>
+                <item name="Encoder" href="/design/encoder-module.html"/>
+                <item name="Event" href="/design/event-module.html"/>
+                <item name="Input" href="/design/input-module.html"/>
+                <item name="JNDI Provider" href="/design/jndi-provider-module.html"/>
+                <item name="Listener" href="/design/listener-module.html"/>
+                <item name="Nexus" href="/design/nexus-module.html"/>
+                <item name="Output" href="/design/output-module.html"/>
+                <item name="Protocol" href="/design/protocol-module.html"/>
+                <item name="RootDSE" href="/design/rootdse-design.html"/>
+                <item name="Schema" href="/design/schema-module.html"/>
+                <item name="SEDA" href="/design/seda-implementation.html"/>
+                <item name="Server Architecture" href="/design/server-architecture.html"/>
+                <item name="Triggers and Procedures" href="/design/triggers-and-procedures.html"/>
+                <item/>
+                <item name="Operations" href="/design/operations/index.html"/>
+        </menu>
+        <menu name="LDAPd Subprojects">
+            <item name="Berkeley" href="/../../backend-blank.html"/>
+            <item name="Common" href="/../../modules/ldapd-common"/>
+            <item name="JDBC" href="/../../modules/ldapd-modjdbc"/>
+            <item name="JDBM" href="/../../modules/ldapd-modjdbm"/>
+            <item name="Replication" href="/../../module-blank.html"/>
+            <item name="SNACC Provider" href="/../../modules/ldapd-snacc-provider"/>
+        </menu>
+    </body>
+</project>

Added: incubator/directory/eve/branches/start/xdocs/stylesheets/tigris.css
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/stylesheets/tigris.css	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,427 @@
+/* contains rules unsuitable for Netscape 4.x; simpler rules are in ns4_only.css. see <http://style.tigris.org/> */
+
+/* colors, backgrounds, borders, link indication */ 
+
+body {
+ background: #fff;
+ color: #000;
+ }
+.app h3, .app h4, .app th, .tabs td, .tabs th, .functnbar {
+ }
+#navcolumn div div.heading  {
+ background-image: none;
+ }
+.app h3, .app h4 {
+ color: #fff;
+ }
+.app h3 {
+ background-color: #036;
+ }
+.app h4 { 
+ background-color: #eee;
+ }
+.a td { 
+ background: #ddd;
+ }
+.b td { 
+ background: #efefef;
+ }
+table, th, td {
+ border: none
+ } 
+.mtb {
+ border-top: solid 1px #ddd;
+ }
+div.colbar {
+ background: #bbb;
+ }
+div#banner {
+ border-top: 1px solid #369;
+ border-bottom: 1px solid #003;
+ }
+div#helptext th {
+ border-bottom: 1px solid #996;
+ border-right: 1px solid #996;
+ }
+div#helptext td {
+ border-bottom: 1px solid #cc9;
+ border-right: 1px solid #cc9;
+ }
+.tabs { 
+ border-bottom: .75em #888 solid;
+ }
+.tabs th, .tabs td {
+ border-right: 1px solid #333;
+ }
+.tabs td {
+ border-bottom: 1px solid #ddd;
+ }
+#navcolumn {
+ background: #eee;
+ border-right: 1px solid #aaa;
+ border-bottom: 1px solid #aaa;
+ }
+#breadcrumbs {
+ border-bottom: 1px solid #aaa;
+ background-color: #ddd;
+ }
+#navcolumn, #breadcrumbs {
+ border-top: 1px solid #fff;
+ }
+#rightcol div.www, #rightcol div.help {
+ border: 1px solid #ddd;
+ }
+div#navcolumn div.focus { 
+ border-top: 1px solid #aaa;
+ border-left: 1px solid #aaa;
+ background-color: #fff;
+ } 
+body.docs div.docs { 
+ background: #fff;
+ border-left: 1px solid #ddd;
+ border-top: 1px solid #ddd;
+ }
+body.docs { 
+ background: #eee url(../images/help_logo.gif) top right no-repeat !important;
+ }
+.docs h3, .docs h4 {
+ border-top: solid 1px #000;
+ }
+#alerterrormessage { 
+ background: url(../images/icon_alert.gif) top left no-repeat !important;
+ }
+.functnbar {
+ background-color: #aaa;
+ }
+.functnbar2, .functnbar3  {
+ background: #aaa url(../images/sw_min.gif) no-repeat bottom left;
+ }
+.functnbar3 {
+ background-color: #ddd;
+ }
+.functnbar, .functnbar2, .functnbar3 {
+ color: #000;
+ }
+.functnbar a, .functnbar2 a, .functnbar3 a {
+ color: #000;
+ text-decoration: underline;
+ }
+#topmodule {
+ background: #ddd;
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #aaa; 
+ border-right: 1px solid #aaa; 
+ }
+#topmodule #issueid {
+ border-right: 1px solid #aaa;
+ }
+a:link, #navcolumn a:visited, .app a:visited, .tasknav a:visited {
+ color: blue;
+ }
+a:active, a:hover, #leftcol a:active, #leftcol a:hover {
+ color: #f30 !important;
+ }
+#login a:link, #login a:visited {
+ color: white; 
+ text-decoration: underline;
+ }
+#banner a:active, #banner a:hover {
+ color: #f90 !important;
+ }
+#leftcol a, #breadcrumbs a  {
+ text-decoration: none;
+ }
+a:link.selfref, a:visited.selfref {
+ color: #555 !important;
+ text-decoration: none;
+ }
+h2 .lastchild {
+ color: #777
+ } 
+.tabs td, .tabs th {
+ background-color: #ddd;
+ }
+.app th {
+ background-color: #bbb;
+ }
+.tabs th {
+ background-color: #888;
+ color: #fff;
+ }
+.axial th {
+ background-color: #ddd;
+ color: black
+ }
+.tabs td {
+ background-color: #ddd;
+ }
+.alert { 
+ color: #c00;
+ }
+.confirm {
+ color: green;
+ }
+.info {
+ color: blue;
+ }
+.selection {
+ background: #ffc;
+ }
+#login {
+ color: #fff;
+ }
+#helptext th {
+ background: #cc9;
+ }
+#helptext td {
+ background: #ffc;
+ }
+.tabs a  {
+ text-decoration: none;
+ }
+#navcolumn div strong {
+ color: #000;
+ }
+#banner, #banner td { 
+ background: #036;
+ color: #fff;
+ }
+body #banner #login a { 
+ color: #fff;
+ }
+
+
+/* font and text properties, exclusive of link indication, alignment, text-indent */
+
+body, th, td, input, select, textarea, h2 small {
+ font-family: Verdana, Helvetica, Arial, sans-serif;
+ }
+code, pre {
+ font-family: 'Andale Mono', Courier, monospace;
+ }
+html body, body th, body td, textarea, h2 small, .app h3, .app h4, #rightcol h3, #bodycol pre, #bodycol code {
+ font-size: x-small;
+ voice-family: "\"}\"";
+ voice-family: inherit;
+ font-size: small
+ }
+html>body, html>body th, html>body td, html>body input, html>body select, html>body textarea, html>body h2 small, html>body .app h3, html>body .app h4, html>body #rightcol h3, html>body #bodycol pre, html>body #bodycol code {
+ font-size: small
+ }
+small, div#footer td, div#login, div#helptext th, div#helptext td, div.tabs th, div.tabs td, input, select, .paginate, .functnbar, .functnbar2, .functnbar3, #breadcrumbs td, .courtesylinks, #rightcol div.help, .colbar, .tasknav, body.docs div#toc {
+ font-size: xx-small;
+ voice-family: "\"}\"";
+ voice-family: inherit;
+ font-size: x-small
+ }
+html>body small, html>body div#footer td, html>body div#login, html>body div#helptext td, html>body div#helptext th, html>body div.tabs th, html>body div.tabs td, html>body input, html>body select, html>body .paginate, html>body .functnbar, html>body .functnbar2, html>body .functnbar3, html>body #breadcrumbs td, html>body .courtesylinks, html>body #rightcol div.help, html>body .colbar, html>body .tasknav, html>body.docs #toc {
+ font-size: x-small
+ }
+#bodycol h2 {
+ font-family: Tahoma, Verdana, Helvetica, Arial, sans-serif;
+ font-size: 1.5em;
+ font-weight: normal;
+ }
+h2 small {
+ font-weight: bold;
+ letter-spacing: .06em;
+ }
+dt {
+ font-weight: bold
+ }
+#login .username {
+ font-weight: bold;
+ }
+h4 {
+ font-size: 1em;
+ }
+#breadcrumbs td {
+ font-weight: bold;
+ }
+.selection {
+ font-weight: bold
+ }
+
+
+/* box properties (exclusive of borders), positioning, alignments, list types, text-indent */
+
+#bodycol h2 {
+ margin-top: .3em;
+ margin-bottom: .5em;
+ }
+p, ul, ol, dl {
+ margin-top: .67em;
+ margin-bottom: .67em;
+ }
+h3, h4 {
+ margin-bottom: 0;
+ }
+form {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+#bodycol {
+ padding-left: 12px;
+ padding-right: 12px;
+ width: 100%;
+ voice-family: "\"}\"";
+ voice-family: inherit;
+ width: auto;
+ }
+html>body #bodycol {
+ width: auto;
+ }
+.docs {
+ line-height: 1.4;
+ }
+.app h3, .app h4 {
+ padding: 5px;
+ margin-right: 2px;
+ margin-left: 2px;
+ }
+.h3 p, .h4 p, .h3 dt, .h4 dt {
+ margin-right: 7px;
+ margin-left: 7px;
+ }
+.tasknav {
+ margin-bottom: 1.33em
+ }
+div.colbar {
+ padding: 4px;
+ margin: 2px 2px 0;
+ }
+.tabs { 
+ margin-top: .67em;
+ margin-right: 2px;
+ margin-left: 2px;
+ }
+#leftcol {
+ padding-bottom: .5em;
+ }
+#breadcrumbs td {
+ vertical-align: middle;
+ padding: 2px 8px;
+ } 
+#rightcol div.www, #rightcol div.help {
+ padding: 0 .5em
+ }
+#navcolumn {
+ margin: -8px -8px 0 -8px;
+ padding: 4px;
+ }
+#navcolumn div {
+ padding-left: 5px
+ }
+div#navcolumn div div {
+ margin-top: .3em;
+ margin-bottom: .3em;
+ }
+div#navcolumn div.focus { 
+ margin-top: -.1em;
+ padding: .2em 4px; 
+ } 
+body.docs #toc { 
+ position: absolute;
+ top: 15px;
+ left: 0px;
+ width: 120px;
+ padding: 0 20px 0 0
+ }
+body.docs #toc ul, #toc ol {
+ margin-left: 0;
+ padding-left: 0;
+ }
+body.docs #toc li {
+ margin-top: 7px;
+ padding-left: 10px;
+ list-style-type: none;
+ }
+body.docs div.docs { 
+ margin: 61px 0 0 150px;
+ padding: 1em 2em 1em 1em !important;
+ }
+.docs p+p {
+ text-indent: 5%;
+ margin-top: -.67em
+ }
+.docs h3, .docs h4 {
+ margin-bottom: .1em;
+ padding-top: .3em;
+ }
+#alerterrormessage { 
+ padding-left: 100px;
+ }
+.functnbar, .functnbar2, .functnbar3 {
+ padding: 5px;
+ margin: .67em 2px;
+ }
+#topmodule td {
+ vertical-align: middle;
+ padding: 2px 8px
+ } 
+body {
+ padding: 1em;
+ }
+body.composite, body.docs {
+ margin: 0;
+ padding: 0;
+ }
+th, td {
+ text-align: left;
+ vertical-align: top 
+ }
+.right {
+ text-align: right !important;
+ }
+.center {
+ text-align: center !important;
+ }
+.tabs td, .tabs th {
+ padding-left: 7px;
+ padding-right: 7px;
+ }
+.axial th {
+ text-align: right;
+ }
+.app .axial td th {
+ text-align: left;
+ }
+body td .stb {
+ margin-top: 1em;
+ text-indent: 0;
+ }
+body td .mtb {
+ margin-top: 2em;
+ text-indent: 0;
+ }
+dd {
+ margin-bottom: .67em;
+ }
+#footer {
+ margin: 4px
+ }
+#helptext {
+ margin-top: 1em
+ }
+#helptext td div {
+ margin: .5em
+ }
+.courtesylinks {
+ margin-top: 1em;
+ padding-top: 1em
+ }
+#navcolumn div {
+ margin-bottom: .5em;
+ }
+#navcolumn div div {
+ margin-top: .3em
+ }
+#navcolumn div div {
+ padding-left: 1em;
+ }
+#banner, #banner td { 
+ vertical-align: middle;
+ }
+body.docs, body.nonav {
+ margin: 1em
+ }

Added: incubator/directory/eve/branches/start/xdocs/temp.xml
==============================================================================
--- (empty file)
+++ incubator/directory/eve/branches/start/xdocs/temp.xml	Thu Jun 24 00:06:35 2004
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<document>
+	<properties>
+		<author email="bearcej at users.sourceforge.net">Jim Bearce</author>
+		<title>LDAPd Documentation Place Holder</title>
+	</properties>
+</document>