catch( ReferralException e ) { LdapResult result = req.getResultResponse().getLdapResult(); ReferralImpl refs = new ReferralImpl(); result.setReferral( refs ); result.setResultCode( ResultCodeEnum.REFERRAL ); result.setErrorMessage( "Encountered referral attempting to handle add request." );   do { refs.addLdapUrl( ( String ) e.getReferralInfo() ); } while( e.skipReferral() ); session.write( req.getResultResponse() ); return; }
    public void messageReceived( IoSession session, Object request )    {        ServerLdapContext ctx;        SearchRequest req = ( SearchRequest ) request;        NamingEnumeration list = null;        String[] ids = null;        Collection retAttrs = new HashSet();        retAttrs.addAll( req.getAttributes() );                // add the search request to the registry of outstanding requests for this session        SessionRegistry.getSingleton().addOutstandingRequest( session, req );        // check the attributes to see if a referral's ref attribute is included        if( retAttrs.size() > 0 && !retAttrs.contains( "ref" ) )        {            retAttrs.add( "ref" );            ids = ( String[] ) retAttrs.toArray( ArrayUtils.EMPTY_STRING_ARRAY );        }        else if( retAttrs.size() > 0 )        {            ids = ( String[] ) retAttrs.toArray( ArrayUtils.EMPTY_STRING_ARRAY );        }        SearchControls controls = getSearchControls( req, ids );        try        {            // ===============================================================            // Find session context            // ===============================================================            boolean isRootDSESearch = isRootDSESearch( req );            // bypass checks to disallow anonymous binds for search on RootDSE with base obj scope            if ( isRootDSESearch )            {                LdapContext unknown = SessionRegistry.getSingleton().getLdapContextOnRootDSEAccess( session, null );                if ( ! ( unknown instanceof ServerLdapContext ) )                {                    ctx = ( ServerLdapContext ) unknown.lookup( "" );                }                else                {                    ctx = ( ServerLdapContext ) unknown;                }            }            // all those search operations are subject to anonymous bind checks when anonymous binda are disallowed            else            {                LdapContext unknown = SessionRegistry.getSingleton().getLdapContext( session, null, true );                if ( ! ( unknown instanceof ServerLdapContext ) )                {                    ctx = ( ServerLdapContext ) unknown.lookup( "" );                }                else                {                    ctx = ( ServerLdapContext ) unknown;                }            }            ctx.addToEnvironment( DEREFALIASES_KEY, req.getDerefAliases().getName() );            if ( req.getControls().containsKey( ManageDsaITControl.CONTROL_OID ) )            {                ctx.addToEnvironment( Context.REFERRAL, "ignore" );            }            else            {                ctx.addToEnvironment( Context.REFERRAL, "throw" );            }            // ===============================================================            // Handle annonymous binds            // ===============================================================            StartupConfiguration cfg = ( StartupConfiguration ) Configuration.toConfiguration( ctx.getEnvironment() );            boolean allowAnonymousBinds = cfg.isAllowAnonymousAccess();            boolean isAnonymousUser = ( ( ServerLdapContext ) ctx ).getPrincipal().getName().trim().equals( "" );            if ( isAnonymousUser && ! allowAnonymousBinds && ! isRootDSESearch )            {                LdapResult result = req.getResultResponse().getLdapResult();                result.setResultCode( ResultCodeEnum.INSUFFICIENTACCESSRIGHTS );                String msg = "Bind failure: Anonymous binds have been disabled!";                result.setErrorMessage( msg );                session.write( req.getResultResponse() );                return;            }            // ===============================================================            // Handle psearch differently            // ===============================================================            PersistentSearchControl psearchControl = ( PersistentSearchControl )                 req.getControls().get( PersistentSearchControl.CONTROL_OID );            if ( psearchControl != null )            {                // there are no limits for psearch processing                controls.setCountLimit( 0 );                controls.setTimeLimit( 0 );                                if ( ! psearchControl.isChangesOnly() )                {                    list = ( ( ServerLdapContext ) ctx ).search( new LdapName( req.getBase() ), req.getFilter(), controls );                    if ( list instanceof AbandonListener )                    {                        req.addAbandonListener( ( AbandonListener ) list );                    }                    if( list.hasMore() )                    {                        Iterator it = new SearchResponseIterator( req, list );                        while( it.hasNext() )                        {                            Response resp = ( Response ) it.next();                            if ( resp instanceof SearchResponseDone )                            {                                // ok if normal search beforehand failed somehow quickly abandon psearch                                ResultCodeEnum rcode = ( ( SearchResponseDone ) resp ).getLdapResult().getResultCode();                                if ( rcode.getValue() != LdapResultEnum.SUCCESS )                                {                                    session.write( resp );                                    return;                                }                                // if search was fine then we returned all entries so now                                // instead of returning the DONE response we break from the                                // loop and user the notification listener to send back                                 // notificationss to the client in never ending search                                else break;                            }                            else                            {                                session.write( resp );                            }                        }                    }                }                                // now we process entries for ever as they change                 PersistentSearchListener handler = new PersistentSearchListener( ctx, session, req );                StringBuffer buf = new StringBuffer();                req.getFilter().printToBuffer( buf );                ctx.addNamingListener( req.getBase(), buf.toString(), controls, handler );                return;            }                        // ===============================================================            // Handle regular search requests from here down            // ===============================================================            /*             * Iterate through all search results building and sending back responses              * for each search result returned.               */            list = ( ( ServerLdapContext ) ctx ).search( new LdapName( req.getBase() ), req.getFilter(), controls );            if ( list instanceof AbandonListener )            {                req.addAbandonListener( ( AbandonListener ) list );            }                        if( list.hasMore() )            {                Iterator it = new SearchResponseIterator( req, list );                while( it.hasNext() )                {                    session.write( it.next() );                }                return;            }            else            {                list.close();                req.getResultResponse().getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );                Iterator it = Collections.singleton( req.getResultResponse() ).iterator();                while( it.hasNext() )                {                    session.write( it.next() );                }                return;            }        }        catch( NamingException e )        {            /*             * From RFC 2251 Section 4.11:             *              * In the event that a server receives an Abandon Request on a Search               * operation in the midst of transmitting responses to the Search, that             * server MUST cease transmitting entry responses to the abandoned             * request immediately, and MUST NOT send the SearchResultDone. Of             * course, the server MUST ensure that only properly encoded LDAPMessage             * PDUs are transmitted.              *              * SO DON'T SEND BACK ANYTHING!!!!!             */            if ( e instanceof OperationAbandonedException )            {                return;            }                        String msg = "failed on search operation";            if ( log.isDebugEnabled() )            {                msg += ":\n" + req + ":\n" + ExceptionUtils.getStackTrace( e );            }            ResultCodeEnum code = null;            if( e instanceof LdapException )            {                code = ( ( LdapException ) e ).getResultCode();            }            else            {                code = ResultCodeEnum.getBestEstimate( e, req.getType() );            }            LdapResult result = req.getResultResponse().getLdapResult();            result.setResultCode( code );            result.setErrorMessage( msg );            if ( ( e.getResolvedName() != null ) &&                    ( ( code == ResultCodeEnum.NOSUCHOBJECT ) ||                      ( code == ResultCodeEnum.ALIASPROBLEM ) ||                      ( code == ResultCodeEnum.INVALIDDNSYNTAX ) ||                      ( code == ResultCodeEnum.ALIASDEREFERENCINGPROBLEM ) ) )            {                result.setMatchedDn( e.getResolvedName().toString() );            }            Iterator it = Collections.singleton( req.getResultResponse() ).iterator();            while( it.hasNext() )            {                session.write( it.next() );            }        }        finally        {            SessionRegistry.getSingleton().removeOutstandingRequest( session, req.getMessageId() );            if ( list != null )            {                try { list.close(); } catch( NamingException e ){ log.error("failed on list.close()", e ); }             }        }    }