String msg = "failed on search operation";
String msg = "failed on search operation: " + e.getMessage();
    public void messageReceived( IoSession session, Object request ) throws Exception    {    	if ( IS_DEBUG )    	{    		log.debug( "Message received : " + request.toString() );    	}    	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 );        }        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;                }                Control[] controls = ( Control[] ) req.getControls().values().toArray( new Control[0] );                ctx.setRequestControls( controls );            }            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-finding-base" );            }            // ===============================================================            // Handle annonymous binds            // ===============================================================            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;            }            // ===============================================================            // Set search limits differently based on user's identity            // ===============================================================            SearchControls controls = null;            if ( isAnonymousUser )            {                controls = getSearchControls( req, ids, false );            }            else if ( ( ( ServerLdapContext ) ctx ).getPrincipal().getName()                .trim().equals( PartitionNexus.ADMIN_PRINCIPAL ) )            {                controls = getSearchControls( req, ids, true );            }            else            {                controls = getSearchControls( req, ids, false );            }                                    // ===============================================================            // 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( req.getBase(), req.getFilter(),                        controls );                    if ( list instanceof AbandonListener )                    {                        req.addAbandonListener( ( AbandonListener ) list );                    }                    if ( list.hasMore() )                    {                        Iterator it = new SearchResponseIterator( req, ctx, list, controls.getSearchScope(), session );                        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( req.getBase(), req.getFilter(), controls );            if ( list instanceof AbandonListener )            {                req.addAbandonListener( ( AbandonListener ) list );            }            if ( list.hasMore() )            {                Iterator it = new SearchResponseIterator( req, ctx, list, controls.getSearchScope(), session );                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 ( 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." );            /* coming up null causing a NPE */            // result.setMatchedDn( e.getResolvedName().toString() );            do            {                refs.addLdapUrl( ( String ) e.getReferralInfo() );            }            while ( e.skipReferral() );            session.write( req.getResultResponse() );            SessionRegistry.getSingleton().removeOutstandingRequest( session, req.getMessageId() );            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( (LdapDN)e.getResolvedName() );            }            Iterator it = Collections.singleton( req.getResultResponse() ).iterator();            while ( it.hasNext() )            {                session.write( it.next() );            }            SessionRegistry.getSingleton().removeOutstandingRequest( session, req.getMessageId() );        }        finally        {            if ( list != null )            {                try                {                    list.close();                }                catch ( NamingException e )                {                    log.error( "failed on list.close()", e );                }            }        }    }