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