| /* |
| * 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() ) ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |