directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1183558 [2/2] - in /directory/apacheds/trunk/core-shared: ./ src/ src/java/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/server/ src/main/java/...
Date Fri, 14 Oct 2011 23:31:27 GMT
Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,1112 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.core.shared.partition;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.naming.ConfigurationException;
+import javax.naming.directory.SearchControls;
+
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.entry.ClonedServerEntry;
+import org.apache.directory.server.core.api.filtering.BaseEntryFilteringCursor;
+import org.apache.directory.server.core.api.filtering.CursorList;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.EntryOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.GetRootDSEOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ListOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
+import org.apache.directory.server.core.api.partition.AbstractPartition;
+import org.apache.directory.server.core.api.partition.Partition;
+import org.apache.directory.server.core.api.partition.PartitionNexus;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.cursor.EmptyCursor;
+import org.apache.directory.shared.ldap.model.cursor.SingletonCursor;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.shared.ldap.model.entry.DefaultEntry;
+import org.apache.directory.shared.ldap.model.entry.DefaultModification;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.entry.Modification;
+import org.apache.directory.shared.ldap.model.entry.ModificationOperation;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.exception.LdapNoSuchAttributeException;
+import org.apache.directory.shared.ldap.model.exception.LdapNoSuchObjectException;
+import org.apache.directory.shared.ldap.model.exception.LdapOperationErrorException;
+import org.apache.directory.shared.ldap.model.exception.LdapOtherException;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.filter.PresenceNode;
+import org.apache.directory.shared.ldap.model.message.SearchScope;
+import org.apache.directory.shared.ldap.model.message.extended.NoticeOfDisconnect;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.name.DnUtils;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.Normalizer;
+import org.apache.directory.shared.ldap.model.schema.UsageEnum;
+import org.apache.directory.shared.ldap.util.tree.DnNode;
+import org.apache.directory.shared.util.DateUtils;
+import org.apache.directory.shared.util.exception.MultiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A root {@link Partition} that contains all other partitions, and
+ * routes all operations to the child partition that matches to its base suffixes.
+ * It also provides some extended operations such as accessing rootDSE and
+ * listing base suffixes.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class DefaultPartitionNexus extends AbstractPartition implements PartitionNexus
+{
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( DefaultPartitionNexus.class );
+
+    /** the fixed id: 'NEXUS' */
+    private static final String ID = "NEXUS";
+    
+    /** Speedup for logs */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** the vendorName string proudly set to: Apache Software Foundation*/
+    private static final String ASF = "Apache Software Foundation";
+
+    /** the read only rootDSE attributes */
+    private final Entry rootDSE;
+
+    /** The DirectoryService instance */
+    private DirectoryService directoryService;
+
+    /** the partitions keyed by normalized suffix strings */
+    private Map<String, Partition> partitions = new HashMap<String, Partition>();
+
+    /** A structure to hold all the partitions */
+    private DnNode<Partition> partitionLookupTree = new DnNode<Partition>();
+
+    /** the system partition */
+    //private Partition system;
+
+    /** A reference to the EntryCSN attributeType */
+    private static AttributeType ENTRY_CSN_AT;
+
+    /** A reference to the ObjectClass attributeType */
+    private static AttributeType OBJECT_CLASS_AT;
+
+    private final List<Modification> mods = new ArrayList<Modification>( 2 );
+
+    private String lastSyncedCtxCsn = null;
+    
+    /** The cn=schema Dn */
+    private Dn subschemSubentryDn;
+
+
+
+    /**
+     * Creates the root nexus singleton of the entire system.  The root DSE has
+     * several attributes that are injected into it besides those that may
+     * already exist.  As partitions are added to the system more namingContexts
+     * attributes are added to the rootDSE.
+     *
+     * @see <a href="http://www.faqs.org/rfcs/rfc3045.html">Vendor Information</a>
+     * @param rootDSE the root entry for the DSA
+     * @throws javax.naming.Exception on failure to initialize
+     */
+    public DefaultPartitionNexus( Entry rootDSE ) throws Exception
+    {
+        id = ID;
+        suffixDn = null;
+            
+        // setup that root DSE
+        this.rootDSE = rootDSE;
+
+        // Add the basic informations
+        rootDSE.put( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, ServerDNConstants.CN_SCHEMA_DN );
+        rootDSE.put( SchemaConstants.SUPPORTED_LDAP_VERSION_AT, "3" );
+        rootDSE.put( SchemaConstants.SUPPORTED_FEATURES_AT, SchemaConstants.FEATURE_ALL_OPERATIONAL_ATTRIBUTES );
+        rootDSE.put( SchemaConstants.SUPPORTED_EXTENSION_AT, NoticeOfDisconnect.EXTENSION_OID );
+
+        // Add the objectClasses
+        rootDSE.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );
+
+        // Add the 'vendor' name and version infos
+        rootDSE.put( SchemaConstants.VENDOR_NAME_AT, ASF );
+
+        Properties props = new Properties();
+
+        try
+        {
+            props.load( getClass().getResourceAsStream( "version.properties" ) );
+        }
+        catch ( IOException e )
+        {
+            LOG.error( I18n.err( I18n.ERR_33 ) );
+        }
+
+        rootDSE.put( SchemaConstants.VENDOR_VERSION_AT, props.getProperty( "apacheds.version", "UNKNOWN" ) );
+        
+        // The rootDSE uuid has been randomly created
+        rootDSE.put( SchemaConstants.ENTRY_UUID_AT, "f290425c-8272-4e62-8a67-92b06f38dbf5" );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#initialize()
+     */
+    protected void doInit() throws Exception
+    {
+        // NOTE: We ignore ContextPartitionConfiguration parameter here.
+        if ( !initialized )
+        {
+            // Add the supported controls
+            Iterator<String> ctrlOidItr = directoryService.getLdapCodecService().registeredControls();
+            
+            while ( ctrlOidItr.hasNext() )
+            {
+                rootDSE.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
+            }
+    
+            schemaManager = directoryService.getSchemaManager();
+            ENTRY_CSN_AT = schemaManager.getAttributeType( SchemaConstants.ENTRY_CSN_AT );
+            OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+    
+            // Initialize and normalize the localy used DNs
+            Dn adminDn = directoryService.getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
+            adminDn.apply( schemaManager );
+    
+            Value<?> attr = rootDSE.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
+            subschemSubentryDn = directoryService.getDnFactory().create( attr.getString() );
+    
+            //initializeSystemPartition( directoryService );
+    
+            List<Partition> initializedPartitions = new ArrayList<Partition>();
+            
+            initializedPartitions.add( 0, directoryService.getSystemPartition() );
+            addContextPartition( directoryService.getSystemPartition() );
+    
+            try
+            {
+                for ( Partition partition : directoryService.getPartitions() )
+                {
+                    addContextPartition( partition );
+                    initializedPartitions.add( partition );
+                }
+    
+                createContextCsnModList();
+    
+                initialized = true;
+            }
+            finally
+            {
+                if ( !initialized )
+                {
+                    Iterator<Partition> i = initializedPartitions.iterator();
+                    
+                    while ( i.hasNext() )
+                    {
+                        Partition partition = i.next();
+                        i.remove();
+                        
+                        try
+                        {
+                            partition.destroy();
+                        }
+                        catch ( Exception e )
+                        {
+                            LOG.warn( "Failed to destroy a partition: " + partition.getSuffixDn(), e );
+                        }
+                        finally
+                        {
+                            unregister( partition );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    private Partition initializeSystemPartition( DirectoryService directoryService ) throws Exception
+    {
+        // initialize system partition first
+        Partition system = directoryService.getSystemPartition();
+
+        // Add root context entry for system partition
+        Dn systemSuffixDn = directoryService.getDnFactory().create( ServerDNConstants.SYSTEM_DN );
+        CoreSession adminSession = directoryService.getAdminSession();
+
+        if ( !system.hasEntry( new EntryOperationContext( adminSession, systemSuffixDn ) ) )
+        {
+            Entry systemEntry = new DefaultEntry( schemaManager, systemSuffixDn );
+            
+            // Add the ObjectClasses
+            systemEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
+                SchemaConstants.ORGANIZATIONAL_UNIT_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );
+            
+            // Add some operational attributes
+            systemEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN );
+            systemEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
+            systemEntry.add( SchemaConstants.ENTRY_CSN_AT, directoryService.getCSN().toString() );
+            systemEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
+            systemEntry.put( DnUtils.getRdnAttributeType( ServerDNConstants.SYSTEM_DN ), DnUtils
+                .getRdnValue( ServerDNConstants.SYSTEM_DN ) );
+            
+            AddOperationContext addOperationContext = new AddOperationContext( adminSession, systemEntry );
+            system.add( addOperationContext );
+        }
+
+        String key = system.getSuffixDn().getNormName();
+
+        if ( partitions.containsKey( key ) )
+        {
+            throw new ConfigurationException( I18n.err( I18n.ERR_263, key ) );
+        }
+
+        synchronized ( partitionLookupTree )
+        {
+            partitions.put( key, system );
+            partitionLookupTree.add( system.getSuffixDn(), system );
+            Attribute namingContexts = rootDSE.get( SchemaConstants.NAMING_CONTEXTS_AT );
+
+            if ( namingContexts == null )
+            {
+                namingContexts = new DefaultAttribute( schemaManager
+                    .getAttributeType( SchemaConstants.NAMING_CONTEXTS_AT ), system.getSuffixDn().getName() );
+                rootDSE.put( namingContexts );
+            }
+            else
+            {
+                namingContexts.add( system.getSuffixDn().getName() );
+            }
+        }
+
+        return system;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#destroy()
+     */
+    protected synchronized void doDestroy()
+    {
+        if ( !initialized )
+        {
+            return;
+        }
+
+        // make sure this loop is not fail fast so all backing stores can
+        // have an attempt at closing down and synching their cached entries
+        for ( String suffix : new HashSet<String>( this.partitions.keySet() ) )
+        {
+            try
+            {
+                removeContextPartition(  directoryService.getDnFactory().create( suffix ) );
+            }
+            catch ( Exception e )
+            {
+                LOG.warn( "Failed to destroy a partition: " + suffix, e );
+            }
+        }
+
+        initialized = false;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setId( String id )
+    {
+        throw new UnsupportedOperationException( I18n.err( I18n.ERR_264 ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setSuffixDn( Dn suffix )
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#sync()
+     */
+    public void sync() throws Exception
+    {
+        MultiException error = null;
+
+        // store the contextCSN value in the entry ou=system
+        // note that this modification shouldn't change the entryCSN value of ou=system entry
+        try
+        {
+            String currentCtxCsn = directoryService.getContextCsn();
+            // update only if the CSN changes
+            if ( ( currentCtxCsn != null ) && !currentCtxCsn.equals( lastSyncedCtxCsn ) )
+            {
+                lastSyncedCtxCsn = currentCtxCsn;
+
+                Attribute contextCsnAt = mods.get( 0 ).getAttribute();
+                contextCsnAt.clear();
+                contextCsnAt.add( lastSyncedCtxCsn );
+
+                Attribute timeStampAt = mods.get( 1 ).getAttribute();
+                timeStampAt.clear();
+                timeStampAt.add( DateUtils.getGeneralizedTime() );
+
+                ModifyOperationContext csnModContext = new ModifyOperationContext( directoryService.getAdminSession(),
+                    directoryService.getSystemPartition().getSuffixDn(), mods );
+                directoryService.getSystemPartition().modify( csnModContext );
+            }
+        }
+        catch ( Exception e )
+        {
+            LOG.warn( "Failed to save the contextCSN attribute value in ou=system entry.", e );
+            if ( error == null )
+            {
+                error = new MultiException( I18n.err( I18n.ERR_265 ) );
+            }
+
+            error.addThrowable( e );
+        }
+
+        for ( Partition partition : this.partitions.values() )
+        {
+            try
+            {
+                partition.sync();
+            }
+            catch ( Exception e )
+            {
+                LOG.warn( "Failed to flush partition data out.", e );
+                if ( error == null )
+                {
+                    //noinspection ThrowableInstanceNeverThrown
+                    error = new MultiException( I18n.err( I18n.ERR_265 ) );
+                }
+
+                // @todo really need to send this info to a monitor
+                error.addThrowable( e );
+            }
+        }
+
+        if ( error != null )
+        {
+            throw error;
+        }
+    }
+
+
+    // ------------------------------------------------------------------------
+    // DirectoryPartition Interface Method Implementations
+    // ------------------------------------------------------------------------
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#add(org.apache.directory.server.core.interceptor.context.AddOperationContext)
+     */
+    public void add( AddOperationContext addContext ) throws LdapException
+    {
+        Partition partition = getPartition( addContext.getDn() );
+        partition.add( addContext );
+
+        Attribute at = addContext.getEntry().get( SchemaConstants.ENTRY_CSN_AT );
+        directoryService.setContextCsn( at.getString() );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#bind(org.apache.directory.server.core.interceptor.context.BindOperationContext)
+     */
+    public void bind( BindOperationContext bindContext ) throws LdapException
+    {
+        Partition partition = getPartition( bindContext.getDn() );
+        partition.bind( bindContext );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#compare(org.apache.directory.server.core.interceptor.context.CompareOperationContext)
+     */
+    public boolean compare( CompareOperationContext compareContext ) throws LdapException
+    {
+        Attribute attr = compareContext.getOriginalEntry().get( compareContext.getAttributeType() );
+
+        // complain if the attribute being compared does not exist in the entry
+        if ( attr == null )
+        {
+            throw new LdapNoSuchAttributeException();
+        }
+
+        // see first if simple match without normalization succeeds
+        if ( attr.contains( compareContext.getValue() ) )
+        {
+            return true;
+        }
+
+        // now must apply normalization to all values (attr and in request) to compare
+
+        /*
+         * Get ahold of the normalizer for the attribute and normalize the request
+         * assertion value for comparisons with normalized attribute values.  Loop
+         * through all values looking for a match.
+         */
+        Normalizer normalizer = compareContext.getAttributeType().getEquality().getNormalizer();
+        Value<?> reqVal = normalizer.normalize( compareContext.getValue() );
+
+        for ( Value<?> value : attr )
+        {
+            Value<?> attrValObj = normalizer.normalize( value );
+
+            if ( attrValObj.equals( reqVal ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#delete(org.apache.directory.server.core.interceptor.context.DeleteOperationContext)
+     */
+    public void delete( DeleteOperationContext deleteContext ) throws LdapException
+    {
+        Partition partition = getPartition( deleteContext.getDn() );
+        partition.delete( deleteContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasEntry( EntryOperationContext hasEntryContext ) throws LdapException
+    {
+        Dn dn = hasEntryContext.getDn();
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "Check if Dn '" + dn + "' exists." );
+        }
+
+        if ( dn.isRootDSE() )
+        {
+            return true;
+        }
+
+        Partition partition = getPartition( dn );
+        
+        return partition.hasEntry( hasEntryContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public EntryFilteringCursor list( ListOperationContext listContext ) throws LdapException
+    {
+        Partition partition = getPartition( listContext.getDn() );
+        
+        return partition.list( listContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
+    {
+        Dn dn = lookupContext.getDn();
+
+        if ( dn.equals( subschemSubentryDn ) )
+        {
+            return new ClonedServerEntry( rootDSE.clone() );
+        }
+
+        // This is for the case we do a lookup on the rootDSE
+        if ( dn.size() == 0 )
+        {
+            Entry retval = new ClonedServerEntry( rootDSE );
+
+            if ( ( lookupContext.getAttrsId() != null ) && !lookupContext.getAttrsId().isEmpty() )
+            {
+                for ( Attribute attribute : rootDSE.getAttributes() )
+                {
+                    AttributeType attributeType = attribute.getAttributeType();
+                    String oid = attributeType.getOid();
+
+                    if ( !lookupContext.getAttrsId().contains( oid ) )
+                    {
+                        retval.removeAttributes( attributeType );
+                    }
+                }
+                
+                return retval;
+            }
+            else
+            {
+                return new ClonedServerEntry( rootDSE );
+            }
+        }
+
+        Partition partition = getPartition( dn );
+        Entry entry =  partition.lookup( lookupContext );
+        
+        if ( entry == null )
+        {
+            LdapNoSuchObjectException e = new LdapNoSuchObjectException( "Attempt to lookup non-existant entry: "
+                + dn.getName() );
+
+            throw e;
+        }
+
+        return entry;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void modify( ModifyOperationContext modifyContext ) throws LdapException
+    {
+        // Special case : if we don't have any modification to apply, just return
+        if ( modifyContext.getModItems().size() == 0 )
+        {
+            return;
+        }
+
+        Partition partition = getPartition( modifyContext.getDn() );
+
+        partition.modify( modifyContext );
+        
+        Entry alteredEntry = modifyContext.getAlteredEntry();
+        
+        if ( alteredEntry != null )
+        {
+            directoryService.setContextCsn( alteredEntry.get( ENTRY_CSN_AT ).getString() );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void move( MoveOperationContext moveContext ) throws LdapException
+    {
+        // Get the current partition
+        Partition partition = getPartition( moveContext.getDn() );
+
+        // We also have to get the new partition as it can be different
+        //Partition newBackend = getPartition( opContext.getNewDn() );
+
+        partition.move( moveContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
+    {
+        Partition partition = getPartition( moveAndRenameContext.getDn() );
+        partition.moveAndRename( moveAndRenameContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void rename( RenameOperationContext renameContext ) throws LdapException
+    {
+        Partition partition = getPartition( renameContext.getDn() );
+        partition.rename( renameContext );
+    }
+
+
+    private EntryFilteringCursor searchRootDSE( SearchOperationContext searchContext ) throws LdapException
+    {
+        SearchControls searchControls = searchContext.getSearchControls();
+
+        String[] ids = searchControls.getReturningAttributes();
+
+        // -----------------------------------------------------------
+        // If nothing is asked for then we just return the entry asis.
+        // We let other mechanisms filter out operational attributes.
+        // -----------------------------------------------------------
+        if ( ( ids == null ) || ( ids.length == 0 ) )
+        {
+            Entry rootDSE = getRootDSE( null );
+            return new BaseEntryFilteringCursor( new SingletonCursor<Entry>( rootDSE ), searchContext );
+        }
+
+        // -----------------------------------------------------------
+        // Collect all the real attributes besides 1.1, +, and * and
+        // note if we've seen these special attributes as well.
+        // -----------------------------------------------------------
+
+        Set<String> realIds = new HashSet<String>();
+        boolean allUserAttributes = searchContext.isAllUserAttributes();
+        boolean allOperationalAttributes = searchContext.isAllOperationalAttributes();
+        boolean noAttribute = searchContext.isNoAttributes();
+
+        for ( String id : ids )
+        {
+            String idTrimmed = id.trim();
+
+            try
+            {
+                realIds.add( schemaManager.getAttributeTypeRegistry().getOidByName( idTrimmed ) );
+            }
+            catch ( Exception e )
+            {
+                realIds.add( idTrimmed );
+            }
+        }
+
+        // return nothing
+        if ( noAttribute )
+        {
+            Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
+            return new BaseEntryFilteringCursor( new SingletonCursor<Entry>( serverEntry ), searchContext );
+        }
+
+        // return everything
+        if ( allUserAttributes && allOperationalAttributes )
+        {
+            Entry rootDSE = getRootDSE( null );
+            return new BaseEntryFilteringCursor( new SingletonCursor<Entry>( rootDSE ), searchContext );
+        }
+
+        Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
+
+        Entry rootDSE = getRootDSE( new GetRootDSEOperationContext( searchContext.getSession() ) );
+
+        for ( Attribute attribute : rootDSE )
+        {
+            AttributeType type = schemaManager.lookupAttributeTypeRegistry( attribute.getUpId() );
+
+            if ( realIds.contains( type.getOid() ) )
+            {
+                serverEntry.put( attribute );
+            }
+            else if ( allUserAttributes && ( type.getUsage() == UsageEnum.USER_APPLICATIONS ) )
+            {
+                serverEntry.put( attribute );
+            }
+            else if ( allOperationalAttributes && ( type.getUsage() != UsageEnum.USER_APPLICATIONS ) )
+            {
+                serverEntry.put( attribute );
+            }
+        }
+
+        return new BaseEntryFilteringCursor( new SingletonCursor<Entry>( serverEntry ), searchContext );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#search(org.apache.directory.server.core.interceptor.context.SearchOperationContext)
+     */
+    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
+    {
+        Dn base = searchContext.getDn();
+        SearchControls searchCtls = searchContext.getSearchControls();
+        ExprNode filter = searchContext.getFilter();
+
+        // TODO since we're handling the *, and + in the EntryFilteringCursor
+        // we may not need this code: we need see if this is actually the
+        // case and remove this code.
+        if ( base.size() == 0 )
+        {
+            // We are searching from the rootDSE. We have to distinguish three cases :
+            // 1) The scope is OBJECT : we have to return the rootDSE entry, filtered
+            // 2) The scope is ONELEVEL : we have to return all the Namin
+            boolean isObjectScope = searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE;
+
+            boolean isOnelevelScope = searchCtls.getSearchScope() == SearchControls.ONELEVEL_SCOPE;
+
+            boolean isSublevelScope = searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE;
+
+            // test for (objectClass=*)
+            boolean isSearchAll = false;
+
+            // We have to be careful, as we may have a filter which is not a PresenceFilter
+            if ( filter instanceof PresenceNode)
+            {
+                isSearchAll = ( ( PresenceNode ) filter ).getAttributeType().equals( OBJECT_CLASS_AT );
+            }
+
+            /*
+             * if basedn is "", filter is "(objectclass=*)" and scope is object
+             * then we have a request for the rootDSE
+             */
+            if ( ( filter instanceof PresenceNode ) && isObjectScope && isSearchAll )
+            {
+                return searchRootDSE( searchContext );
+            }
+            else if ( isObjectScope && ( !isSearchAll ) )
+            {
+                return new BaseEntryFilteringCursor( new EmptyCursor<Entry>(), searchContext );
+            }
+            else if ( isOnelevelScope )
+            {
+                List<EntryFilteringCursor> cursors = new ArrayList<EntryFilteringCursor>();
+
+                for ( Partition partition : partitions.values() )
+                {
+                    Dn contextDn = partition.getSuffixDn();
+                    EntryOperationContext hasEntryContext = new EntryOperationContext( null, contextDn );
+                    // search only if the context entry exists
+                    if( partition.hasEntry( hasEntryContext ) )
+                    {
+                        searchContext.setDn( contextDn );
+                        searchContext.setScope( SearchScope.OBJECT );
+                        cursors.add( partition.search( searchContext ) );
+                    }
+                }
+
+                return new CursorList( cursors, searchContext );
+            }
+            else if ( isSublevelScope )
+            {
+                List<EntryFilteringCursor> cursors = new ArrayList<EntryFilteringCursor>();
+
+                for ( Partition partition : partitions.values() )
+                {
+                    Entry entry = partition.lookup( new LookupOperationContext( directoryService.getAdminSession(),
+                        partition.getSuffixDn() ) );
+
+                    if ( entry != null )
+                    {
+                        Partition backend = getPartition( entry.getDn() );
+                        searchContext.setDn( entry.getDn() );
+                        cursors.add( backend.search( searchContext ) );
+                    }
+                }
+
+                // don't feed the above Cursors' list to a BaseEntryFilteringCursor it is skipping the naming context entry of each partition
+                return new CursorList( cursors, searchContext );
+            }
+
+            // TODO : handle searches based on the RootDSE
+            throw new LdapNoSuchObjectException();
+        }
+
+        if ( !base.isSchemaAware() )
+        {
+            base.apply( schemaManager );
+        }
+
+        Partition backend = getPartition( base );
+
+        return backend.search( searchContext );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#unbind(org.apache.directory.server.core.interceptor.context.UnbindOperationContext)
+     */
+    public void unbind( UnbindOperationContext unbindContext ) throws LdapException
+    {
+        Partition partition = getPartition( unbindContext.getDn() );
+        partition.unbind( unbindContext );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#getRootDSE(org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext)
+     */
+    public Entry getRootDSE( GetRootDSEOperationContext getRootDSEContext )
+    {
+        return rootDSE.clone();
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#addContextPartition(org.apache.directory.server.core.interceptor.context.AddContextPartitionOperationContext)
+     */
+    public synchronized void addContextPartition( Partition partition ) throws LdapException
+    {
+        // Turn on default indices
+        String key = partition.getSuffixDn().getNormName();
+
+        if ( partitions.containsKey( key ) )
+        {
+            throw new LdapOtherException( I18n.err( I18n.ERR_263, key ) );
+        }
+
+        if ( !partition.isInitialized() )
+        {
+            partition.initialize();
+        }
+
+        synchronized ( partitionLookupTree )
+        {
+            Dn partitionSuffix = partition.getSuffixDn();
+
+            if ( partitionSuffix == null )
+            {
+                throw new LdapOtherException( I18n.err( I18n.ERR_267, partition.getId() ) );
+            }
+
+            partitions.put( partitionSuffix.getNormName(), partition );
+            partitionLookupTree.add( partition.getSuffixDn(), partition );
+
+            Attribute namingContexts = rootDSE.get( SchemaConstants.NAMING_CONTEXTS_AT );
+
+            if ( namingContexts == null )
+            {
+                namingContexts = new DefaultAttribute( schemaManager
+                    .lookupAttributeTypeRegistry( SchemaConstants.NAMING_CONTEXTS_AT ), partitionSuffix.getName() );
+                rootDSE.put( namingContexts );
+            }
+            else
+            {
+                namingContexts.add( partitionSuffix.getName() );
+            }
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#removeContextPartition(Dn partitionDN)
+     */
+    public synchronized void removeContextPartition( Dn partitionDn )
+        throws LdapException
+    {
+        // Get the Partition name. It's a Dn.
+        String key = partitionDn.getNormName();
+
+        // Retrieve this partition from the aprtition's table
+        Partition partition = partitions.get( key );
+
+        if ( partition == null )
+        {
+            String msg = I18n.err( I18n.ERR_34, key );
+            LOG.error( msg );
+            throw new LdapNoSuchObjectException( msg );
+        }
+
+        String partitionSuffix = partition.getSuffixDn().getName();
+
+        // Retrieve the namingContexts from the RootDSE : the partition
+        // suffix must be present in those namingContexts
+        Attribute namingContexts = rootDSE.get( SchemaConstants.NAMING_CONTEXTS_AT );
+
+        if ( namingContexts != null )
+        {
+            if ( namingContexts.contains( partitionSuffix ) )
+            {
+                namingContexts.remove( partitionSuffix );
+            }
+            else
+            {
+                String msg = I18n.err( I18n.ERR_35, key );
+                LOG.error( msg );
+                throw new LdapNoSuchObjectException( msg );
+            }
+        }
+
+        // Update the partition tree
+        synchronized ( partitionLookupTree )
+        {
+            partitionLookupTree.remove( partition.getSuffixDn() );
+        }
+        
+        partitions.remove( key );
+
+        try
+        {
+            partition.destroy();
+        }
+        catch ( Exception e )
+        {
+            throw new LdapOperationErrorException( e.getMessage(), e );
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#getPartition(org.apache.directory.shared.ldap.model.name.Dn)
+     */
+    public Partition getPartition( Dn dn ) throws LdapException
+    {
+        Partition parent = null;
+        
+        synchronized ( partitionLookupTree )
+        {
+            parent = partitionLookupTree.getElement( dn );
+        }
+
+        if ( parent == null )
+        {
+            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_268, dn ) );
+        }
+        else
+        {
+            return parent;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Dn getSuffixDn( Dn dn ) throws LdapException
+    {
+        Partition partition = getPartition( dn );
+
+        return partition.getSuffixDn();
+    }
+
+
+    /* (non-Javadoc)
+     */
+    public Set<String> listSuffixes() throws LdapException
+    {
+        return Collections.unmodifiableSet( partitions.keySet() );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#registerSupportedExtensions(java.util.Set)
+     */
+    public void registerSupportedExtensions( Set<String> extensionOids ) throws LdapException
+    {
+        Attribute supportedExtension = rootDSE.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
+
+        if ( supportedExtension == null )
+        {
+            rootDSE.put( SchemaConstants.SUPPORTED_EXTENSION_AT, (String)null );
+            supportedExtension = rootDSE.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
+        }
+
+        for ( String extensionOid : extensionOids )
+        {
+            supportedExtension.add( extensionOid );
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.partition.PartitionNexus#registerSupportedSaslMechanisms(java.util.Set)
+     */
+    public void registerSupportedSaslMechanisms( Set<String> supportedSaslMechanisms ) throws LdapException
+    {
+        Attribute supportedSaslMechanismsAt = null;
+
+        supportedSaslMechanismsAt = new DefaultAttribute( schemaManager.lookupAttributeTypeRegistry( SchemaConstants.SUPPORTED_SASL_MECHANISMS_AT ) );
+
+        for ( String saslMechanism : supportedSaslMechanisms )
+        {
+            supportedSaslMechanismsAt.add( saslMechanism );
+        }
+        
+        rootDSE.add( supportedSaslMechanismsAt );
+    }
+
+
+    /**
+     * Unregisters an ContextPartition with this BackendManager.  Called for each
+     * registered Backend right befor it is to be stopped.  This prevents
+     * protocol server requests from reaching the Backend and effectively puts
+     * the ContextPartition's naming context offline.
+     *
+     * Operations against the naming context should result in an LDAP BUSY
+     * result code in the returnValue if the naming context is not online.
+     *
+     * @param partition ContextPartition component to unregister with this
+     * BackendNexus.
+     * @throws Exception if there are problems unregistering the partition
+     */
+    private void unregister( Partition partition ) throws Exception
+    {
+        Attribute namingContexts = rootDSE.get( SchemaConstants.NAMING_CONTEXTS_AT );
+
+        if ( namingContexts != null )
+        {
+            namingContexts.remove( partition.getSuffixDn().getName() );
+        }
+
+        partitions.remove( partition.getSuffixDn().getName() );
+    }
+
+
+    /**
+     * @return the directoryService
+     */
+    public DirectoryService getDirectoryService()
+    {
+        return directoryService;
+    }
+
+
+    /**
+     * @param directoryService the directoryService to set
+     */
+    public void setDirectoryService( DirectoryService directoryService )
+    {
+        this.directoryService = directoryService;
+    }
+
+
+    private void createContextCsnModList() throws LdapException
+    {
+        Modification contextCsnMod = new DefaultModification();
+        contextCsnMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
+        DefaultAttribute contextCsnAt = new DefaultAttribute( schemaManager
+            .lookupAttributeTypeRegistry( SchemaConstants.CONTEXT_CSN_AT ) );
+        contextCsnMod.setAttribute( contextCsnAt );
+
+        mods.add( contextCsnMod );
+
+        Modification timeStampMod = new DefaultModification();
+        timeStampMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
+        DefaultAttribute timeStampAt = new DefaultAttribute( schemaManager
+            .lookupAttributeTypeRegistry( SchemaConstants.MODIFY_TIMESTAMP_AT ) );
+        timeStampMod.setAttribute( timeStampAt );
+
+        mods.add( timeStampMod );
+    }
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/LdapClassLoader.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/LdapClassLoader.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/LdapClassLoader.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/LdapClassLoader.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,211 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.shared.sp;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.StringValue;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.AndNode;
+import org.apache.directory.shared.ldap.model.filter.BranchNode;
+import org.apache.directory.shared.ldap.model.filter.EqualityNode;
+import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.model.message.SearchScope;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A class loader that loads classes from an LDAP DIT.
+ * 
+ * <p>
+ * This loader looks for an configuration entry whose Dn is
+ * determined by defaultSearchContextsConfig variable. If there is such
+ * an entry it gets the search contexts from the entry and searches the 
+ * class to be loaded in those contexts.
+ * If there is no default search context configuration entry it searches
+ * the class in the whole DIT. 
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdapClassLoader extends ClassLoader
+{
+    private static final Logger LOG = LoggerFactory.getLogger( LdapClassLoader.class );
+    public static final String DEFAULT_SEARCH_CONTEXTS_CONFIG = "cn=classLoaderDefaultSearchContext,ou=configuration,ou=system";
+    
+    private Dn defaultSearchDn;
+    private DirectoryService directoryService;
+
+    /** A storage for the ObjectClass attributeType */
+    private AttributeType OBJECT_CLASS_AT;
+
+    
+    public LdapClassLoader( DirectoryService directoryService ) throws LdapException
+    {
+        super( LdapClassLoader.class.getClassLoader() );
+        this.directoryService = directoryService;
+        defaultSearchDn = directoryService.getDnFactory().create( DEFAULT_SEARCH_CONTEXTS_CONFIG );
+        
+        OBJECT_CLASS_AT = directoryService.getSchemaManager().getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+    }
+
+    
+    private byte[] findClassInDIT( List<Dn> searchContexts, String name ) throws ClassNotFoundException
+    {
+        // Set up the search filter
+        BranchNode filter = new AndNode( );
+        AttributeType fqjcnAt = directoryService.getSchemaManager().getAttributeType( "fullyQualifiedJavaClassName" );
+        filter.addNode( new EqualityNode<String>( fqjcnAt, new StringValue( name ) ) );
+        filter.addNode( new EqualityNode<String>( OBJECT_CLASS_AT,
+            new StringValue( ApacheSchemaConstants.JAVA_CLASS_OC ) ) );
+        
+        try
+        {
+            for ( Dn base : searchContexts )
+            {
+                EntryFilteringCursor cursor = null;
+                try
+                {
+                    cursor = directoryService.getAdminSession()
+                        .search( base, SearchScope.SUBTREE, filter, AliasDerefMode.DEREF_ALWAYS, null );
+                    
+                    cursor.beforeFirst();
+                    if ( cursor.next() ) // there should be only one!
+                    {
+                        LOG.debug( "Class {} found under {} search context.", name, base );
+                        Entry classEntry = cursor.get();
+
+                        if ( cursor.next() )
+                        {
+                            Entry other = cursor.get();
+                            LOG.warn( "More than one class found on classpath at locations: {} \n\tand {}", 
+                                classEntry, other );
+                        }
+
+                        return classEntry.get( "javaClassByteCode" ).getBytes();
+                    }
+                }
+                finally
+                {
+                    if ( cursor != null )
+                    {
+                        cursor.close();
+                    }
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            LOG.error( I18n.err( I18n.ERR_69, name ), e );
+        }
+
+        throw new ClassNotFoundException();
+    }
+    
+    
+    public Class<?> findClass( String name ) throws ClassNotFoundException
+    {
+        byte[] classBytes = null;
+
+        try 
+        {   
+            // TODO we should cache this information and register with the event
+            // service to get notified if this changes so we can update the cached
+            // copy - there's absolutely no reason why we should be performing this
+            // lookup every time!!!
+            
+            Entry configEntry = null;
+            
+            try
+            {
+                configEntry = directoryService.getAdminSession().lookup( defaultSearchDn );
+            }
+            catch ( LdapException e )
+            {
+                LOG.debug( "No configuration data found for class loader default search contexts." );
+            }
+            
+            if ( configEntry != null )
+            {
+                List<Dn> searchContexts = new ArrayList<Dn>();
+                Attribute attr = configEntry.get( "classLoaderDefaultSearchContext" );
+                
+                for ( Value<?> val : attr )
+                {
+                    Dn dn = directoryService.getDnFactory().create( val.getString() );
+                    searchContexts.add( dn );
+                }
+                
+                try
+                {
+                    classBytes = findClassInDIT( searchContexts, name );
+                    
+                    LOG.debug( "Class " + name + " found under default search contexts." );
+                }
+                catch ( ClassNotFoundException e )
+                {
+                    LOG.debug( "Class " + name + " could not be found under default search contexts." );
+                }
+            }
+            
+            if ( classBytes == null )
+            {
+                List<Dn> namingContexts = new ArrayList<Dn>();
+                
+                Set<String> suffixes = directoryService.getPartitionNexus().listSuffixes();
+
+                for ( String suffix:suffixes )
+                {
+                    Dn dn = directoryService.getDnFactory().create( suffix );
+                    namingContexts.add( dn );
+                }
+                
+                classBytes = findClassInDIT( namingContexts, name );
+            }
+        } 
+        catch ( ClassNotFoundException e )
+        {
+            String msg = I18n.err( I18n.ERR_293, name );
+            LOG.debug( msg );
+            throw new ClassNotFoundException( msg );
+        }
+        catch ( Exception e ) 
+        {
+            String msg = I18n.err( I18n.ERR_70, name );
+            LOG.error( msg, e );
+            throw new ClassNotFoundException( msg );
+        }
+        
+        return defineClass( name, classBytes, 0, classBytes.length );
+    }
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngine.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngine.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngine.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngine.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.shared.sp;
+
+
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+
+
+/**
+ * An abstraction over stored procedure execution depending on the type of the language supported.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface StoredProcEngine
+{
+    
+    /**
+     * Returns the unique identifier of the supported stored procedure language.
+     * 
+     */
+    public String getSPLangId();
+    
+    
+    /**
+     * Registers an entry found to be contaning a stored procedure unit which this engine can operate on.
+     *
+     * <p>
+     * This method should be called before an attempt to invoke a stored procedure via this Engine.
+     */
+    public void setSPUnitEntry( final Entry spUnit );
+    
+    
+    /**
+     * Invokes the stored procedure handled by the engine.
+     * 
+     * @param fullSPName A fully qualified name of the stored procedure including its unit name.
+     * @param spArgs A list or arguments to be passed to the stored procedure. It should be an empty array if there aren't any parameters defined.
+     * @return The value obtained from invoked procedure. The client should know what will return exactly so that it can downcast to the appropriate type.
+     * @throws org.apache.directory.shared.ldap.model.exception.LdapException If an error occurs during invocation.
+     */
+    public Object invokeProcedure( CoreSession session, String fullSPName, Object[] spArgs ) throws LdapException;
+
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngineConfig.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngineConfig.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngineConfig.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcEngineConfig.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.server.core.shared.sp;
+
+
+/**
+ * A configuration wrapper for {@link StoredProcEngine}s.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface StoredProcEngineConfig
+{
+    /**
+     * Returns the type of the associated {@link StoredProcEngine}.
+     * 
+     */
+    public Class<? extends StoredProcEngine> getStoredProcEngineType();
+    
+    
+    /**
+     * Returns the unique language identifier of the {@link StoredProcEngine}.
+     * 
+     */
+    public String getStoredProcLangId();
+
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcExecutionManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcExecutionManager.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcExecutionManager.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcExecutionManager.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,153 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.core.shared.sp;
+
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.directory.SearchControls;
+
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.api.entry.ClonedServerEntry;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.entry.StringValue;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.EqualityNode;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.model.message.SearchScope;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.AttributeTypeOptions;
+
+
+/**
+ * A Factory type class which holds a registry of supported {@link StoredProcEngineConfig}s. A container reference
+ * as the base for Stored Procedure storage on the DIT is also handled by this class.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoredProcExecutionManager
+{
+    private final static Set<AttributeTypeOptions> EMPTY_ATTRIBS = Collections.emptySet();
+    
+    private final String storedProcContainer;
+
+    private final List<StoredProcEngineConfig> storedProcEngineConfigs;
+
+
+    /**
+     * Creates a {@link StoredProcExecutionManager} instance.
+     * 
+     * @param storedProcContainer The base of the DIT subtree used for storing stored procedure units.
+     * @param storedProcEngineConfigs A list of {@link StoredProcEngineConfig}s to register different {@link StoredProcEngine}s with this manager.
+     */
+    public StoredProcExecutionManager( final String storedProcContainer, final List<StoredProcEngineConfig> storedProcEngineConfigs )
+    {
+        this.storedProcContainer = storedProcContainer;
+        this.storedProcEngineConfigs = storedProcEngineConfigs;
+    }
+    
+    /**
+     * Finds and returns a stored procedure unit entry whose identifier name
+     * is extracted from fullSPName.
+     * 
+     * @param session the session with a core directory service
+     * @param fullSPName Full name of the Stored Procedure including the unit name.
+     * @return The entry associated with the SP Unit.
+     * @throws Exception If the unit cannot be located or any other error occurs.
+     */
+    public Entry findStoredProcUnit( CoreSession session, String fullSPName ) throws Exception
+    {
+        SearchControls controls = new SearchControls();
+        controls.setReturningAttributes( SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        String spUnitName = StoredProcUtils.extractStoredProcUnitName( fullSPName );
+        
+        AttributeType storeProcUnitNamAT = session.getDirectoryService()
+            .getSchemaManager().lookupAttributeTypeRegistry( "storedProcUnitName" );
+        ExprNode filter = new EqualityNode<String>( storeProcUnitNamAT, new StringValue( storeProcUnitNamAT, spUnitName ) );
+        Dn dn = session.getDirectoryService().getDnFactory().create( storedProcContainer );
+        EntryFilteringCursor results = session.search( dn, SearchScope.SUBTREE, filter,
+            AliasDerefMode.DEREF_ALWAYS, EMPTY_ATTRIBS );
+        if ( results.first() )
+        {
+            Entry entry = results.get();
+            results.close();
+            
+            return entry;
+        }
+        
+        return null;
+    }
+
+
+    /**
+     * Initializes and returns a {@link StoredProcEngine} instance which can operate on spUnitEntry
+     * considering its specific stored procedure language.
+     * 
+     * @param spUnitEntry The entry which a {@link StoredProcEngine} type will be mathched with respect to the language identifier.
+     * @return A {@link StoredProcEngine} associated with spUnitEntry.
+     * @throws org.apache.directory.shared.ldap.model.exception.LdapException If no {@link StoredProcEngine} that can be associated with the language identifier in spUnitEntry can be found.
+     */
+    public StoredProcEngine getStoredProcEngineInstance( Entry spUnitEntry ) throws LdapException
+    {
+        String spLangId = ( String ) ((ClonedServerEntry)spUnitEntry).getOriginalEntry().get( "storedProcLangId" ).getString();
+
+        for ( StoredProcEngineConfig engineConfig : storedProcEngineConfigs )
+        {
+            if ( engineConfig.getStoredProcLangId().equalsIgnoreCase( spLangId ) )
+            {
+                Class<? extends StoredProcEngine> engineType = engineConfig.getStoredProcEngineType();
+                StoredProcEngine engine;
+                
+                try
+                {
+                    engine = engineType.newInstance();
+                }
+                catch ( InstantiationException e )
+                {
+                    LdapException ne = new LdapException( e.getMessage(), e );
+                    ne.initCause( e );
+                    throw ne;
+                }
+                catch ( IllegalAccessException e )
+                {
+                    LdapException ne = new LdapException( e.getMessage(), e );
+                    ne.initCause( e );
+                    throw ne;
+                }
+                
+                engine.setSPUnitEntry( (Entry)((ClonedServerEntry)spUnitEntry).getOriginalEntry() );
+                return engine;
+            }
+
+        }
+
+        throw new LdapException( I18n.err( I18n.ERR_294, spLangId ) );
+
+    }
+
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcUtils.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcUtils.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/StoredProcUtils.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.server.core.shared.sp;
+
+
+/**
+ * A utility class for working with Stored Procedures.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoredProcUtils
+{
+    
+    /** The delimiter used to tokenize a full SP name into the unit and SP name */
+    public static final String SPUnitDelimiter = ":";
+
+    public static String extractStoredProcName( String fullSPName )
+    {
+        int delimiter = fullSPName.lastIndexOf( SPUnitDelimiter );
+        String spName = fullSPName.substring( delimiter + SPUnitDelimiter.length() );
+        return spName;
+    }
+    
+    public static String extractStoredProcUnitName( String fullSPName )
+    {
+        int delimiter = fullSPName.lastIndexOf( SPUnitDelimiter );
+        String className = fullSPName.substring( 0, delimiter );
+        return className;
+    }
+    
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngine.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngine.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngine.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngine.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,135 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.server.core.shared.sp.java;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.shared.sp.StoredProcEngine;
+import org.apache.directory.server.core.shared.sp.StoredProcUtils;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.util.MethodUtils;
+
+
+/**
+ * A {@link StoredProcEngine} implementation specific to Java stored procedures.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class JavaStoredProcEngine implements StoredProcEngine
+{
+
+    public static final String STORED_PROC_LANG_ID = "Java";
+
+    private Entry spUnit;
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.sp.StoredProcEngine#invokeProcedure(OperationContext, String, Object[])
+     */
+    public Object invokeProcedure( CoreSession session, String fullSPName, Object[] spArgs ) throws LdapException
+    {
+        Attribute javaByteCode = spUnit.get( "javaByteCode" );
+        String spName = StoredProcUtils.extractStoredProcName( fullSPName );
+        String className = StoredProcUtils.extractStoredProcUnitName( fullSPName );
+
+        ClassLoader loader = new LdapJavaStoredProcClassLoader( javaByteCode );
+        Class<?> clazz;
+        
+        try
+        {
+            clazz = loader.loadClass( className );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            throw new LdapException( e );
+        }
+
+        Class<?>[] types = getTypesFromValues( spArgs );
+
+        Method proc;
+        try
+        {
+            proc = MethodUtils.getAssignmentCompatibleMethod(clazz, spName, types);
+        }
+        catch ( NoSuchMethodException e )
+        {
+            throw new LdapException( e );
+        }
+        try
+        {
+            return proc.invoke( null, spArgs );
+        }
+        catch ( IllegalArgumentException e )
+        {
+            throw new LdapException( e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new LdapException( e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw new LdapException( e );
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.sp.StoredProcEngine#getSPLangId()
+     */
+    public String getSPLangId()
+    {
+        return STORED_PROC_LANG_ID;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.sp.StoredProcEngine#setSPUnitEntry(javax.naming.directory.Attributes)
+     */
+    public void setSPUnitEntry( Entry spUnit )
+    {
+        this.spUnit = spUnit;
+    }
+
+
+    private Class<?>[] getTypesFromValues( Object[] values )
+    {
+        List<Class<?>> types = new ArrayList<Class<?>>();
+
+        for ( Object obj : values )
+        {
+            types.add( obj.getClass() );
+        }
+
+        return types.toArray( EMPTY_CLASS_ARRAY );
+    }
+
+    private static Class<?>[] EMPTY_CLASS_ARRAY = new Class[ 0 ];
+
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngineConfig.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngineConfig.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngineConfig.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/JavaStoredProcEngineConfig.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.server.core.shared.sp.java;
+
+import org.apache.directory.server.core.shared.sp.StoredProcEngine;
+import org.apache.directory.server.core.shared.sp.StoredProcEngineConfig;
+
+
+/**
+ * A {@link StoredProcEngineConfig} implementation specific to Java stored procedures.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class JavaStoredProcEngineConfig implements StoredProcEngineConfig
+{
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.sp.StoredProcEngineConfig#getStoredProcEngineType()
+     */
+    public Class<? extends StoredProcEngine> getStoredProcEngineType()
+    {
+        return JavaStoredProcEngine.class;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.sp.StoredProcEngineConfig#getStoredProcLangId()
+     */
+    public String getStoredProcLangId()
+    {
+        return JavaStoredProcEngine.STORED_PROC_LANG_ID;
+    }
+
+}

Added: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/LdapJavaStoredProcClassLoader.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/LdapJavaStoredProcClassLoader.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/LdapJavaStoredProcClassLoader.java (added)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/sp/java/LdapJavaStoredProcClassLoader.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.server.core.shared.sp.java;
+
+
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+
+
+/**
+ * A class loader that loads a class from an attribute.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdapJavaStoredProcClassLoader extends ClassLoader
+{
+    private Attribute javaByteCodeAttr;
+
+
+    public LdapJavaStoredProcClassLoader( Attribute javaByteCodeAttr )
+    {
+        // Critical call to super class constructor. Required for true plumbing of class loaders.
+        super( LdapJavaStoredProcClassLoader.class.getClassLoader() );
+
+        this.javaByteCodeAttr = javaByteCodeAttr;
+    }
+
+
+    public Class<?> findClass( String name ) throws ClassNotFoundException
+    {
+        byte[] classBytes;
+        
+        try
+        {
+            classBytes = javaByteCodeAttr.getBytes();
+        }
+        catch ( LdapException e )
+        {
+            throw new ClassNotFoundException();
+        }
+
+        return defineClass( name, classBytes, 0, classBytes.length );
+    }
+}

Added: directory/apacheds/trunk/core-shared/src/main/resources/org/apache/directory/server/core/shared/partition/version.properties
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/resources/org/apache/directory/server/core/shared/partition/version.properties?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/resources/org/apache/directory/server/core/shared/partition/version.properties (added)
+++ directory/apacheds/trunk/core-shared/src/main/resources/org/apache/directory/server/core/shared/partition/version.properties Fri Oct 14 23:31:26 2011
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+apacheds.version=${pom.version}

Added: directory/apacheds/trunk/core-shared/src/test/java/org/apache/directory/server/core/shared/sp/StoredProcUtilsTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/test/java/org/apache/directory/server/core/shared/sp/StoredProcUtilsTest.java?rev=1183558&view=auto
==============================================================================
--- directory/apacheds/trunk/core-shared/src/test/java/org/apache/directory/server/core/shared/sp/StoredProcUtilsTest.java (added)
+++ directory/apacheds/trunk/core-shared/src/test/java/org/apache/directory/server/core/shared/sp/StoredProcUtilsTest.java Fri Oct 14 23:31:26 2011
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.server.core.shared.sp;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class StoredProcUtilsTest
+{
+    @Test
+    public void testSPNameTokenization()
+    {
+        String fullSPName = "Greeter:seyHello";
+        String expectedSPUnitName = "Greeter";
+        String expectedSPName = "seyHello";
+        
+        String actualSPUnitName = StoredProcUtils.extractStoredProcUnitName( fullSPName );
+        String actualSPName = StoredProcUtils.extractStoredProcName( fullSPName );
+        
+        assertEquals( expectedSPUnitName, actualSPUnitName );
+        assertEquals( expectedSPName, actualSPName );
+    }
+
+}



Mime
View raw message