blob: 0932ac7fdb7aef993c719c7c9c0b214d07820719 [file] [log] [blame]
/*
* 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.studio.ldapbrowser.core.jobs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.naming.directory.SearchControls;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.message.controls.PagedResults;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.url.LdapUrl;
import org.apache.directory.api.util.Strings;
import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
import org.apache.directory.studio.connection.core.Connection;
import org.apache.directory.studio.connection.core.Controls;
import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
import org.apache.directory.studio.connection.core.StudioControl;
import org.apache.directory.studio.connection.core.io.api.StudioSearchResult;
import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry;
import org.apache.directory.studio.ldapbrowser.core.events.SearchUpdateEvent;
import org.apache.directory.studio.ldapbrowser.core.model.AttributeHierarchy;
import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
import org.apache.directory.studio.ldapbrowser.core.model.ISearchResult;
import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter;
import org.apache.directory.studio.ldapbrowser.core.model.impl.BaseDNEntry;
import org.apache.directory.studio.ldapbrowser.core.model.impl.ContinuedSearchResultEntry;
import org.apache.directory.studio.ldapbrowser.core.model.impl.Entry;
import org.apache.directory.studio.ldapbrowser.core.model.impl.SearchContinuation;
import org.apache.directory.studio.ldapbrowser.core.model.impl.Value;
import org.apache.directory.studio.ldapbrowser.core.utils.JNDIUtils;
import org.apache.directory.studio.ldapbrowser.core.utils.Utils;
/**
* Runnable to perform search operations.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class SearchRunnable implements StudioConnectionBulkRunnableWithProgress
{
/** The searches. */
protected ISearch[] searches;
/** The searches to perform. */
protected ISearch[] searchesToPerform;
/**
* Creates a new instance of SearchRunnable.
*
* @param searches the searches
*/
public SearchRunnable( ISearch[] searches )
{
this.searches = searches;
this.searchesToPerform = searches;
}
/**
* Creates a new instance of SearchRunnable.
*
* @param search the search
* @param searchToPerform the search to perform
*/
private SearchRunnable( ISearch search, ISearch searchToPerform )
{
this.searches = new ISearch[]
{ search };
this.searchesToPerform = new ISearch[]
{ searchToPerform };
}
/**
* {@inheritDoc}
*/
public Connection[] getConnections()
{
Connection[] connections = new Connection[searches.length];
for ( int i = 0; i < connections.length; i++ )
{
connections[i] = searches[i].getBrowserConnection().getConnection();
}
return connections;
}
/**
* {@inheritDoc}
*/
public String getName()
{
return BrowserCoreMessages.jobs__search_name;
}
/**
* {@inheritDoc}
*/
public Object[] getLockedObjects()
{
List<Object> l = new ArrayList<Object>();
l.addAll( Arrays.asList( searches ) );
return l.toArray();
}
/**
* {@inheritDoc}
*/
public String getErrorMessage()
{
return searches.length == 1 ? BrowserCoreMessages.jobs__search_error_1
: BrowserCoreMessages.jobs__search_error_n;
}
/**
* {@inheritDoc}
*/
public void run( StudioProgressMonitor monitor )
{
monitor.beginTask( " ", searches.length + 1 ); //$NON-NLS-1$
monitor.reportProgress( " " ); //$NON-NLS-1$
for ( int pi = 0; pi < searches.length; pi++ )
{
ISearch search = searches[pi];
ISearch searchToPerform = searchesToPerform[pi];
monitor.setTaskName( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__search_task, new String[]
{ search.getName() } ) );
monitor.worked( 1 );
if ( search.getBrowserConnection() != null )
{
// reset search results
search.setSearchResults( new ISearchResult[0] );
search.getResponseControls().clear();
search.setNextPageSearchRunnable( null );
search.setTopPageSearchRunnable( null );
searchToPerform.setSearchResults( new ISearchResult[0] );
searchToPerform.setNextPageSearchRunnable( null );
searchToPerform.setTopPageSearchRunnable( null );
searchToPerform.getResponseControls().clear();
do
{
// perform search
searchAndUpdateModel( searchToPerform.getBrowserConnection(), searchToPerform, monitor );
if ( search != searchToPerform )
{
// merge search results
ISearchResult[] sr1 = search.getSearchResults();
ISearchResult[] sr2 = searchToPerform.getSearchResults();
ISearchResult[] sr = new ISearchResult[sr1.length + sr2.length];
System.arraycopy( sr1, 0, sr, 0, sr1.length );
System.arraycopy( sr2, 0, sr, sr1.length, sr2.length );
search.setSearchResults( sr );
}
else
{
// set search results
search.setSearchResults( searchToPerform.getSearchResults() );
}
// check response controls
ISearch clonedSearch = ( ISearch ) searchToPerform.clone();
clonedSearch.getResponseControls().clear();
PagedResults prResponseControl = null;
PagedResults prRequestControl = null;
for ( org.apache.directory.api.ldap.model.message.Control responseControl : searchToPerform
.getResponseControls() )
{
if ( responseControl instanceof PagedResults )
{
prResponseControl = ( PagedResults ) responseControl;
}
}
for ( Iterator<Control> it = clonedSearch.getControls().iterator(); it.hasNext(); )
{
Control requestControl = it.next();
if ( requestControl instanceof PagedResults )
{
prRequestControl = ( PagedResults ) requestControl;
it.remove();
}
}
searchToPerform = null;
// paged search
if ( prResponseControl != null && prRequestControl != null )
{
PagedResults nextPrc = Controls.newPagedResultsControl( prRequestControl.getSize(),
prResponseControl.getCookie() );
ISearch nextPageSearch = ( ISearch ) clonedSearch.clone();
nextPageSearch.getResponseControls().clear();
nextPageSearch.getControls().add( nextPrc );
if ( search.isPagedSearchScrollMode() )
{
if ( ArrayUtils.isNotEmpty( prRequestControl.getCookie() ) )
{
// create top page search runnable, same as original search
ISearch topPageSearch = ( ISearch ) search.clone();
topPageSearch.getResponseControls().clear();
SearchRunnable topPageSearchRunnable = new SearchRunnable( search, topPageSearch );
search.setTopPageSearchRunnable( topPageSearchRunnable );
}
if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() ) )
{
// create next page search runnable
SearchRunnable nextPageSearchRunnable = new SearchRunnable( search, nextPageSearch );
search.setNextPageSearchRunnable( nextPageSearchRunnable );
}
}
else
{
// transparently continue search, till count limit is reached
if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() )
&& ( search.getCountLimit() == 0 || search.getSearchResults().length < search
.getCountLimit() ) )
{
searchToPerform = nextPageSearch;
}
}
}
}
while ( searchToPerform != null );
}
}
}
/**
* {@inheritDoc}
*/
public void runNotification( StudioProgressMonitor monitor )
{
for ( int pi = 0; pi < searches.length; pi++ )
{
EventRegistry.fireSearchUpdated( new SearchUpdateEvent( searches[pi],
SearchUpdateEvent.EventDetail.SEARCH_PERFORMED ), this );
}
}
/**
* Searches the directory and updates the browser model.
*
* @param browserConnection the browser connection
* @param search the search
* @param monitor the progress monitor
*/
public static void searchAndUpdateModel( IBrowserConnection browserConnection, ISearch search,
StudioProgressMonitor monitor )
{
if ( browserConnection.getConnection() == null )
{
return;
}
try
{
if ( !monitor.isCanceled() )
{
// add returning attributes for children and alias detection
SearchParameter searchParameter = getSearchParameter( search );
ArrayList<ISearchResult> searchResultList = new ArrayList<ISearchResult>();
ArrayList<SearchContinuation> searchContinuationList = new ArrayList<SearchContinuation>();
StudioSearchResultEnumeration enumeration = null;
// search
try
{
enumeration = search( browserConnection, searchParameter, monitor );
// iterate through the search result
while ( !monitor.isCanceled() && enumeration != null && enumeration.hasMore() )
{
StudioSearchResult sr = enumeration.next();
boolean isContinuedSearchResult = sr.isContinuedSearchResult();
LdapUrl searchContinuationUrl = sr.getSearchContinuationUrl();
if ( searchContinuationUrl == null )
{
Dn dn = sr.getDn();
IEntry entry = null;
Connection resultConnection = sr.getConnection();
IBrowserConnection resultBrowserConnection = BrowserCorePlugin.getDefault()
.getConnectionManager().getBrowserConnection( resultConnection );
if ( resultBrowserConnection == null )
{
resultBrowserConnection = browserConnection;
}
// get entry from cache or create it
entry = resultBrowserConnection.getEntryFromCache( dn );
if ( entry == null )
{
entry = createAndCacheEntry( resultBrowserConnection, dn, monitor );
// If the entry is still null, we return
// See https://issues.apache.org/jira/browse/DIRSTUDIO-865
if ( entry == null )
{
return;
}
}
// initialize special flags
initFlags( entry, sr, searchParameter );
// fill the attributes
fillAttributes( entry, sr, search.getSearchParameter() );
if ( isContinuedSearchResult )
{
// the result is from a continued search
// we create a special entry that displays the URL of the entry
entry = new ContinuedSearchResultEntry( resultBrowserConnection, dn );
}
searchResultList
.add( new org.apache.directory.studio.ldapbrowser.core.model.impl.SearchResult( entry,
search ) );
}
else
{
//entry = new ContinuedSearchResultEntry( resultBrowserConnection, dn );
SearchContinuation searchContinuation = new SearchContinuation( search,
searchContinuationUrl );
searchContinuationList.add( searchContinuation );
}
monitor
.reportProgress( searchResultList.size() == 1 ? BrowserCoreMessages.model__retrieved_1_entry
: BrowserCoreMessages.bind( BrowserCoreMessages.model__retrieved_n_entries,
new String[]
{ Integer.toString( searchResultList.size() ) } ) );
}
}
catch ( Exception e )
{
int ldapStatusCode = JNDIUtils.getLdapStatusCode( e );
if ( ldapStatusCode == 3 || ldapStatusCode == 4 || ldapStatusCode == 11 )
{
search.setCountLimitExceeded( true );
}
else
{
monitor.reportError( e );
}
}
// check for response controls
try
{
if ( enumeration != null )
{
for ( org.apache.directory.api.ldap.model.message.Control control : enumeration
.getResponseControls() )
{
search.getResponseControls().add( control );
if ( control instanceof PagedResults )
{
search.setCountLimitExceeded(
ArrayUtils.isNotEmpty( ( ( PagedResults ) control ).getCookie() ) );
}
}
}
}
catch ( Exception e )
{
monitor.reportError( e );
}
monitor.reportProgress( searchResultList.size() == 1 ? BrowserCoreMessages.model__retrieved_1_entry
: BrowserCoreMessages.bind( BrowserCoreMessages.model__retrieved_n_entries, new String[]
{ Integer.toString( searchResultList.size() ) } ) );
monitor.worked( 1 );
search.setSearchResults( ( ISearchResult[] ) searchResultList
.toArray( new ISearchResult[searchResultList.size()] ) );
search.setSearchContinuations( ( SearchContinuation[] ) searchContinuationList
.toArray( new SearchContinuation[searchContinuationList.size()] ) );
}
}
catch ( Exception e )
{
if ( search != null )
{
search.setSearchResults( new ISearchResult[0] );
}
monitor.reportError( e );
}
}
public static StudioSearchResultEnumeration search( IBrowserConnection browserConnection, SearchParameter parameter,
StudioProgressMonitor monitor )
{
if ( browserConnection == null )
{
return null;
}
String searchBase = parameter.getSearchBase().getName();
SearchControls searchControls = new SearchControls();
SearchScope scope = parameter.getScope();
switch ( scope )
{
case OBJECT:
searchControls.setSearchScope( SearchControls.OBJECT_SCOPE );
break;
case ONELEVEL:
searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
break;
case SUBTREE:
searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
break;
default:
searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
}
searchControls.setReturningAttributes( parameter.getReturningAttributes() );
searchControls.setCountLimit( parameter.getCountLimit() );
int timeLimit = parameter.getTimeLimit() * 1000;
if ( timeLimit > 1 )
{
timeLimit--;
}
searchControls.setTimeLimit( timeLimit );
String filter = parameter.getFilter();
AliasDereferencingMethod aliasesDereferencingMethod = parameter.getAliasesDereferencingMethod();
ReferralHandlingMethod referralsHandlingMethod = parameter.getReferralsHandlingMethod();
Control[] controls = null;
if ( parameter.getControls() != null )
{
controls = parameter.getControls().toArray( new Control[0] );
}
StudioSearchResultEnumeration result = browserConnection
.getConnection()
.getConnectionWrapper()
.search( searchBase, filter, searchControls, aliasesDereferencingMethod, referralsHandlingMethod, controls,
monitor, null );
return result;
}
private static SearchParameter getSearchParameter( ISearch search )
{
SearchParameter searchParameter = ( SearchParameter ) search.getSearchParameter().clone();
// add children detetion attributes
if ( search.isInitHasChildrenFlag() )
{
if ( search.getBrowserConnection().getSchema()
.hasAttributeTypeDescription( SchemaConstants.HAS_SUBORDINATES_AT )
&& !Utils.containsIgnoreCase( Arrays.asList( searchParameter.getReturningAttributes() ),
SchemaConstants.HAS_SUBORDINATES_AT ) )
{
String[] returningAttributes = new String[searchParameter.getReturningAttributes().length + 1];
System.arraycopy( searchParameter.getReturningAttributes(), 0, returningAttributes, 0,
searchParameter.getReturningAttributes().length );
returningAttributes[returningAttributes.length - 1] = SchemaConstants.HAS_SUBORDINATES_AT;
searchParameter.setReturningAttributes( returningAttributes );
}
else if ( search.getBrowserConnection().getSchema()
.hasAttributeTypeDescription( SchemaConstants.NUM_SUBORDINATES_AT )
&& !Utils.containsIgnoreCase( Arrays.asList( searchParameter.getReturningAttributes() ),
SchemaConstants.NUM_SUBORDINATES_AT ) )
{
String[] returningAttributes = new String[searchParameter.getReturningAttributes().length + 1];
System.arraycopy( searchParameter.getReturningAttributes(), 0, returningAttributes, 0,
searchParameter.getReturningAttributes().length );
returningAttributes[returningAttributes.length - 1] = SchemaConstants.NUM_SUBORDINATES_AT;
searchParameter.setReturningAttributes( returningAttributes );
}
else if ( search.getBrowserConnection().getSchema()
.hasAttributeTypeDescription( SchemaConstants.SUBORDINATE_COUNT_AT )
&& !Utils.containsIgnoreCase( Arrays.asList( searchParameter.getReturningAttributes() ),
SchemaConstants.SUBORDINATE_COUNT_AT ) )
{
String[] returningAttributes = new String[searchParameter.getReturningAttributes().length + 1];
System.arraycopy( searchParameter.getReturningAttributes(), 0, returningAttributes, 0,
searchParameter.getReturningAttributes().length );
returningAttributes[returningAttributes.length - 1] = SchemaConstants.SUBORDINATE_COUNT_AT;
searchParameter.setReturningAttributes( returningAttributes );
}
}
// always add the objectClass attribute, we need it
// - to detect alias and referral entries
// - to determine the entry's icon
// - to determine must and may attributes
if ( !Utils.containsIgnoreCase( Arrays.asList( searchParameter.getReturningAttributes() ),
SchemaConstants.OBJECT_CLASS_AT )
&& !Utils.containsIgnoreCase( Arrays.asList( searchParameter.getReturningAttributes() ),
SchemaConstants.ALL_USER_ATTRIBUTES ) )
{
String[] returningAttributes = new String[searchParameter.getReturningAttributes().length + 1];
System.arraycopy( searchParameter.getReturningAttributes(), 0, returningAttributes, 0,
searchParameter.getReturningAttributes().length );
returningAttributes[returningAttributes.length - 1] = SchemaConstants.OBJECT_CLASS_AT;
searchParameter.setReturningAttributes( returningAttributes );
}
// filter controls if not supported by server
if ( searchParameter.getControls() != null )
{
IBrowserConnection connection = search.getBrowserConnection();
Set<String> supportedConrolSet = new HashSet<String>();
if ( connection.getRootDSE() != null
&& connection.getRootDSE().getAttribute( SchemaConstants.SUPPORTED_CONTROL_AT ) != null )
{
IAttribute scAttribute = connection.getRootDSE().getAttribute( SchemaConstants.SUPPORTED_CONTROL_AT );
String[] supportedControls = scAttribute.getStringValues();
for ( int i = 0; i < supportedControls.length; i++ )
{
supportedConrolSet.add( Strings.toLowerCase( supportedControls[i] ) );
}
}
List<Control> controls = searchParameter.getControls();
for ( Iterator<Control> it = controls.iterator(); it.hasNext(); )
{
Control control = it.next();
if ( !supportedConrolSet.contains( Strings.toLowerCase( control.getOid() ) ) )
{
it.remove();
}
}
}
return searchParameter;
}
/**
* Creates the entry and puts it into the BrowserConnection's entry cache.
*
* @param browserConnection the browser connection
* @param dn the Dn of the entry
* @param monitor
*
* @return the created entry
*/
private static IEntry createAndCacheEntry( IBrowserConnection browserConnection, Dn dn,
StudioProgressMonitor monitor )
{
StudioProgressMonitor dummyMonitor = new StudioProgressMonitor( monitor );
IEntry entry = null;
// build tree to parent
LinkedList<Dn> parentDnList = new LinkedList<Dn>();
Dn parentDn = dn;
while ( parentDn != null && browserConnection.getEntryFromCache( parentDn ) == null )
{
parentDnList.addFirst( parentDn );
parentDn = parentDn.getParent();
}
for ( Dn aDn : parentDnList )
{
parentDn = aDn.getParent();
if ( parentDn == null )
{
// only the root DSE has a null parent
entry = browserConnection.getRootDSE();
}
else if ( !parentDn.isEmpty() && browserConnection.getEntryFromCache( parentDn ) != null )
{
// a normal entry has a parent but the parent isn't the rootDSE
IEntry parentEntry = browserConnection.getEntryFromCache( parentDn );
entry = new Entry( parentEntry, aDn.getRdn() );
entry.setDirectoryEntry( true );
parentEntry.addChild( entry );
parentEntry.setChildrenInitialized( true );
parentEntry.setHasMoreChildren( true );
parentEntry.setHasChildrenHint( true );
browserConnection.cacheEntry( entry );
}
else
{
// we have a base Dn, check if the entry really exists in LDAP
// this is to avoid that a node "dc=com" is created for "dc=example,dc=com" context entry
SearchParameter searchParameter = new SearchParameter();
searchParameter.setSearchBase( aDn );
searchParameter.setFilter( null );
searchParameter.setReturningAttributes( ISearch.NO_ATTRIBUTES );
searchParameter.setScope( SearchScope.OBJECT );
searchParameter.setCountLimit( 1 );
searchParameter.setTimeLimit( 0 );
searchParameter.setAliasesDereferencingMethod( browserConnection.getAliasesDereferencingMethod() );
searchParameter.setReferralsHandlingMethod( browserConnection.getReferralsHandlingMethod() );
searchParameter.setInitHasChildrenFlag( true );
dummyMonitor.reset();
StudioSearchResultEnumeration enumeration = search( browserConnection, searchParameter, dummyMonitor );
try
{
if ( enumeration != null && enumeration.hasMore() )
{
// create base Dn entry
entry = new BaseDNEntry( aDn, browserConnection );
browserConnection.getRootDSE().addChild( entry );
browserConnection.cacheEntry( entry );
enumeration.close();
}
}
catch ( LdapException e )
{
}
}
}
return entry;
}
/**
* Initializes the following flags of the entry:
* <ul>
* <li>hasChildren</li>
* <li>isAlias</li>
* <li>isReferral</li>
* <li>isSubentry</li>
* </ul>
*
* @param entry the entry
* @param sr the the JNDI search result
* @param searchParameter the search parameters
*/
private static void initFlags( IEntry entry, StudioSearchResult sr, SearchParameter searchParameter )
{
for ( Attribute attribute : sr.getEntry() )
{
if ( attribute != null )
{
String attributeDescription = attribute.getUpId();
if ( SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( attributeDescription ) )
{
if ( entry.getAttribute( attributeDescription ) != null )
{
entry.deleteAttribute( entry.getAttribute( attributeDescription ) );
}
entry.addAttribute( new org.apache.directory.studio.ldapbrowser.core.model.impl.Attribute( entry,
attributeDescription ) );
}
for ( org.apache.directory.api.ldap.model.entry.Value valueObject : attribute )
{
if ( valueObject.isHumanReadable() )
{
String value = valueObject.getString();
if ( searchParameter.isInitHasChildrenFlag() )
{
// hasChildren flag
if ( SchemaConstants.HAS_SUBORDINATES_AT.equalsIgnoreCase( attributeDescription ) )
{
if ( "FALSE".equalsIgnoreCase( value ) ) //$NON-NLS-1$
{
entry.setHasChildrenHint( false );
}
}
if ( SchemaConstants.NUM_SUBORDINATES_AT.equalsIgnoreCase( attributeDescription ) )
{
if ( "0".equalsIgnoreCase( value ) ) //$NON-NLS-1$
{
entry.setHasChildrenHint( false );
}
}
if ( SchemaConstants.SUBORDINATE_COUNT_AT.equalsIgnoreCase( attributeDescription ) )
{
if ( "0".equalsIgnoreCase( value ) ) //$NON-NLS-1$
{
entry.setHasChildrenHint( false );
}
}
}
if ( SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( attributeDescription ) )
{
if ( SchemaConstants.ALIAS_OC.equalsIgnoreCase( value ) )
{
entry.setAlias( true );
entry.setHasChildrenHint( false );
}
if ( SchemaConstants.REFERRAL_OC.equalsIgnoreCase( value ) )
{
entry.setReferral( true );
entry.setHasChildrenHint( false );
}
IAttribute ocAttribute = entry.getAttribute( attributeDescription );
Value ocValue = new Value( ocAttribute, value );
ocAttribute.addValue( ocValue );
}
}
}
}
}
if ( ( searchParameter.getControls() != null && searchParameter.getControls().contains(
StudioControl.SUBENTRIES_CONTROL ) )
|| ISearch.FILTER_SUBENTRY.equalsIgnoreCase( searchParameter.getFilter() ) )
{
entry.setSubentry( true );
entry.setHasChildrenHint( false );
}
}
/**
* Fills the attributes and values of the search result into the entry.
* Clears existing attributes and values in the entry.
*
* @param entry the entry
* @param sr the JNDI search result
* @param searchParameter the search parameters
*/
private static void fillAttributes( IEntry entry, StudioSearchResult sr, SearchParameter searchParameter )
{
if ( searchParameter.getReturningAttributes() == null || searchParameter.getReturningAttributes().length > 0 )
{
// clear old attributes defined as returning attributes or clear all
if ( searchParameter.getReturningAttributes() != null )
{
String[] ras = searchParameter.getReturningAttributes();
// special case *
if ( Arrays.asList( ras ).contains( SchemaConstants.ALL_USER_ATTRIBUTES ) )
{
// clear all user attributes
IAttribute[] oldAttributes = entry.getAttributes();
for ( int i = 0; oldAttributes != null && i < oldAttributes.length; i++ )
{
if ( !oldAttributes[i].isOperationalAttribute() )
{
entry.deleteAttribute( oldAttributes[i] );
}
}
}
// special case +
if ( Arrays.asList( ras ).contains( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) )
{
// clear all operational attributes
IAttribute[] oldAttributes = entry.getAttributes();
for ( int i = 0; oldAttributes != null && i < oldAttributes.length; i++ )
{
if ( oldAttributes[i].isOperationalAttribute() )
{
entry.deleteAttribute( oldAttributes[i] );
}
}
}
for ( int r = 0; r < ras.length; r++ )
{
// clear attributes requested from server, also include sub-types
AttributeHierarchy ah = entry.getAttributeWithSubtypes( ras[r] );
if ( ah != null )
{
for ( Iterator<IAttribute> it = ah.iterator(); it.hasNext(); )
{
IAttribute attribute = it.next();
entry.deleteAttribute( attribute );
}
}
}
}
else
{
// clear all
IAttribute[] oldAttributes = entry.getAttributes();
for ( int i = 0; oldAttributes != null && i < oldAttributes.length; i++ )
{
entry.deleteAttribute( oldAttributes[i] );
}
}
// additional clear old attributes if the record contains the attribute
for ( Attribute attribute : sr.getEntry() )
{
String attributeDescription = attribute.getUpId();
IAttribute oldAttribute = entry.getAttribute( attributeDescription );
if ( oldAttribute != null )
{
entry.deleteAttribute( oldAttribute );
}
}
// set new attributes and values
for ( Attribute attribute : sr.getEntry() )
{
String attributeDescription = attribute.getUpId();
if ( attribute.iterator().hasNext() )
{
IAttribute studioAttribute = null;
if ( entry.getAttribute( attributeDescription ) == null )
{
studioAttribute = new org.apache.directory.studio.ldapbrowser.core.model.impl.Attribute( entry,
attributeDescription );
entry.addAttribute( studioAttribute );
}
else
{
studioAttribute = entry.getAttribute( attributeDescription );
}
for ( org.apache.directory.api.ldap.model.entry.Value value : attribute )
{
if ( value.isHumanReadable() )
{
studioAttribute.addValue( new Value( studioAttribute, value.getString() ) );
}
else
{
studioAttribute.addValue( new Value( studioAttribute, value.getBytes() ) );
}
}
}
}
}
}
}