001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.extensions; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.LinkedHashSet; 033 034 import org.opends.server.api.DirectoryThread; 035 import org.opends.server.core.DirectoryServer; 036 import org.opends.server.protocols.internal.InternalClientConnection; 037 import org.opends.server.protocols.internal.InternalSearchListener; 038 import org.opends.server.protocols.internal.InternalSearchOperation; 039 import org.opends.server.types.DereferencePolicy; 040 import org.opends.server.types.DirectoryException; 041 import org.opends.server.types.DN; 042 import org.opends.server.types.LDAPURL; 043 import org.opends.server.types.MembershipException; 044 import org.opends.server.types.ResultCode; 045 import org.opends.server.types.SearchFilter; 046 import org.opends.server.types.SearchResultEntry; 047 import org.opends.server.types.SearchResultReference; 048 import org.opends.server.types.SearchScope; 049 050 import static org.opends.messages.ExtensionMessages.*; 051 import org.opends.server.loggers.ErrorLogger; 052 053 /** 054 * This class implements a Directory Server thread that will be used to perform 055 * a background search to retrieve all of the members of a dynamic group. 056 * <BR><BR> 057 */ 058 public class DynamicGroupSearchThread 059 // FIXME -- Would it be better to implement this class using an Executor 060 // rather than always creating a custom thread? 061 extends DirectoryThread 062 implements InternalSearchListener 063 { 064 // The set of base DNs for the search requests. 065 private final DN[] baseDNs; 066 067 // The member list with which this search thread is associated. 068 private final DynamicGroupMemberList memberList; 069 070 // A counter used to keep track of which search is currently in progress. 071 private int searchCounter; 072 073 // The set of member URLs for determining whether entries match the criteria. 074 private final LDAPURL[][] memberURLs; 075 076 // The set of search filters for the search requests. 077 private final SearchFilter[] searchFilters; 078 079 080 081 /** 082 * Creates a new dynamic group search thread that is associated with the 083 * provided member list and that will perform the search using the provided 084 * information. 085 * 086 * @param memberList The dynamic group member list with which this thread is 087 * associated. 088 * @param baseDNs The set of base DNs to use for the search requests. 089 * @param filters The set of search filters to use for the search 090 * requests. 091 * @param memberURLs The set of member URLs to use when determining if 092 * entries match the necessary group criteria. 093 */ 094 public DynamicGroupSearchThread(DynamicGroupMemberList memberList, 095 DN[] baseDNs, SearchFilter[] filters, 096 LDAPURL[][] memberURLs) 097 { 098 super("Dynamic Group Search Thread " + memberList.getDynamicGroupDN()); 099 100 this.memberList = memberList; 101 this.baseDNs = baseDNs; 102 this.searchFilters = filters; 103 this.memberURLs = memberURLs; 104 105 searchCounter = 0; 106 } 107 108 109 110 /** 111 * Performs the set of searches and provides the results to the associated 112 * member list. 113 */ 114 public void run() 115 { 116 InternalClientConnection conn = 117 InternalClientConnection.getRootConnection(); 118 LinkedHashSet<String> attributes = new LinkedHashSet<String>(0); 119 120 for (searchCounter = 0; searchCounter < baseDNs.length; searchCounter++) 121 { 122 InternalSearchOperation searchOperation = 123 conn.processSearch(baseDNs[searchCounter], SearchScope.WHOLE_SUBTREE, 124 DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, 125 false, searchFilters[searchCounter], attributes, 126 this); 127 128 ResultCode resultCode = searchOperation.getResultCode(); 129 if (resultCode != ResultCode.SUCCESS) 130 { 131 if (resultCode == ResultCode.NO_SUCH_OBJECT) 132 { 133 Message message = WARN_DYNAMICGROUP_NONEXISTENT_BASE_DN. 134 get(String.valueOf(baseDNs[searchCounter]), 135 String.valueOf(memberList.getDynamicGroupDN())); 136 ErrorLogger.logError(message); 137 continue; 138 } 139 else 140 { 141 Message message = 142 ERR_DYNAMICGROUP_INTERNAL_SEARCH_FAILED.get( 143 String.valueOf(baseDNs[searchCounter]), 144 String.valueOf(searchFilters[searchCounter]), 145 String.valueOf(memberList.getDynamicGroupDN()), 146 String.valueOf(resultCode), 147 String.valueOf(searchOperation.getErrorMessage())); 148 if (! memberList.addResult( 149 new MembershipException(message, true))) 150 { 151 memberList.setSearchesCompleted(); 152 return; 153 } 154 } 155 } 156 } 157 158 memberList.setSearchesCompleted(); 159 } 160 161 162 163 /** 164 * {@inheritDoc} 165 */ 166 public void handleInternalSearchEntry(InternalSearchOperation searchOperation, 167 SearchResultEntry searchEntry) 168 throws DirectoryException 169 { 170 for (LDAPURL url : memberURLs[searchCounter]) 171 { 172 if (url.matchesEntry(searchEntry)) 173 { 174 if (! memberList.addResult(searchEntry)) 175 { 176 Message message = ERR_DYNAMICGROUP_CANNOT_RETURN_ENTRY. 177 get(String.valueOf(searchEntry.getDN()), 178 String.valueOf(memberList.getDynamicGroupDN())); 179 throw new DirectoryException( 180 DirectoryServer.getServerErrorResultCode(), message); 181 } 182 183 return; 184 } 185 } 186 } 187 188 189 190 /** 191 * {@inheritDoc} 192 */ 193 public void handleInternalSearchReference( 194 InternalSearchOperation searchOperation, 195 SearchResultReference searchReference) 196 { 197 // No implementation required. 198 } 199 } 200