1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.collective;
18
19
20 import org.apache.ldap.server.DirectoryServiceConfiguration;
21 import org.apache.ldap.server.interceptor.BaseInterceptor;
22 import org.apache.ldap.server.interceptor.NextInterceptor;
23 import org.apache.ldap.server.configuration.InterceptorConfiguration;
24 import org.apache.ldap.server.partition.DirectoryPartitionNexus;
25 import org.apache.ldap.server.schema.AttributeTypeRegistry;
26 import org.apache.ldap.server.subtree.SubentryService;
27 import org.apache.ldap.server.invocation.InvocationStack;
28 import org.apache.ldap.server.invocation.Invocation;
29 import org.apache.ldap.server.enumeration.SearchResultFilteringEnumeration;
30 import org.apache.ldap.server.enumeration.SearchResultFilter;
31 import org.apache.ldap.common.filter.ExprNode;
32 import org.apache.ldap.common.name.LdapName;
33 import org.apache.ldap.common.schema.AttributeType;
34 import org.apache.ldap.common.message.LockableAttributeImpl;
35
36 import javax.naming.NamingException;
37 import javax.naming.NamingEnumeration;
38 import javax.naming.Name;
39 import javax.naming.directory.Attributes;
40 import javax.naming.directory.SearchControls;
41 import javax.naming.directory.Attribute;
42 import javax.naming.directory.SearchResult;
43 import java.util.Map;
44 import java.util.Set;
45 import java.util.HashSet;
46 import java.util.Collections;
47
48
49 /***
50 * An interceptor based service dealing with collective attribute
51 * management. This service intercepts read operations on entries to
52 * inject collective attribute value pairs into the response based on
53 * the entires inclusion within collectiveAttributeSpecificAreas and
54 * collectiveAttributeInnerAreas.
55 *
56 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
57 * @version $Rev$
58 */
59 public class CollectiveAttributeService extends BaseInterceptor
60 {
61 /***
62 * the search result filter to use for collective attribute injection
63 */
64 private final SearchResultFilter SEARCH_FILTER = new SearchResultFilter()
65 {
66 public boolean accept( Invocation invocation, SearchResult result, SearchControls controls )
67 throws NamingException
68 {
69 return filter( result.getAttributes() );
70 }
71 };
72
73 private AttributeTypeRegistry registry = null;
74 private DirectoryPartitionNexus nexus = null;
75
76
77 public void init( DirectoryServiceConfiguration factoryCfg, InterceptorConfiguration cfg ) throws NamingException
78 {
79 super.init( factoryCfg, cfg );
80 nexus = factoryCfg.getPartitionNexus();
81 registry = factoryCfg.getGlobalRegistries().getAttributeTypeRegistry();
82 }
83
84
85 /***
86 * Adds the set of collective attributes contained in subentries referenced
87 * by the entry. All collective attributes that are not exclused are added
88 * to the entry from all subentries.
89 *
90 * @param entry the entry to have the collective attributes injected
91 * @throws NamingException if there are problems accessing subentries
92 */
93 private void addCollectiveAttributes( Attributes entry ) throws NamingException
94 {
95 Attribute subentries = entry.get( SubentryService.COLLECTIVE_ATTRIBUTE_SUBENTRIES );
96
97 if ( subentries == null )
98 {
99 return;
100 }
101
102
103
104
105
106
107
108 Attribute collectiveExclusions = entry.get( "collectiveExclusions" );
109 Set exclusions;
110 if ( collectiveExclusions != null )
111 {
112 if ( collectiveExclusions.contains( "2.5.18.0" ) ||
113 collectiveExclusions.contains( "excludeAllCollectiveAttributes" ) )
114 {
115 return;
116 }
117
118 exclusions = new HashSet();
119 for ( int ii = 0; ii < collectiveExclusions.size(); ii++ )
120 {
121 AttributeType attrType = registry.lookup( ( String ) collectiveExclusions.get( ii ) );
122 exclusions.add( attrType.getOid() );
123 }
124 }
125 else
126 {
127 exclusions = Collections.EMPTY_SET;
128 }
129
130
131
132
133
134
135 for ( int ii = 0; ii < subentries.size(); ii++ )
136 {
137 String subentryDnStr = ( String ) subentries.get( ii );
138 Name subentryDn = new LdapName( subentryDnStr );
139 Attributes subentry = nexus.lookup( subentryDn );
140 NamingEnumeration attrIds = subentry.getIDs();
141 while ( attrIds.hasMore() )
142 {
143 String attrId = ( String ) attrIds.next();
144 AttributeType attrType = registry.lookup( attrId );
145
146
147 if ( exclusions.contains( attrType.getOid() ) )
148 {
149 continue;
150 }
151
152
153
154
155
156
157
158
159
160 if ( attrType.isCollective() )
161 {
162 Attribute subentryColAttr = subentry.get( attrId );
163 Attribute entryColAttr = entry.get( attrId );
164
165
166 if ( entryColAttr == null )
167 {
168 entryColAttr = new LockableAttributeImpl( attrId );
169 entry.put( entryColAttr );
170 }
171
172
173 for ( int jj = 0; jj < subentryColAttr.size(); jj++ )
174 {
175 entryColAttr.add( subentryColAttr.get( jj ) );
176 }
177 }
178 }
179 }
180 }
181
182
183 /***
184 * Filter that injects collective attributes into the entry.
185 *
186 * @param attributes the resultant attributes with added collective attributes
187 * @return true always
188 */
189 private boolean filter( Attributes attributes ) throws NamingException
190 {
191 addCollectiveAttributes( attributes );
192 return true;
193 }
194
195
196 private void filter( Name dn, Attributes entry, String[] ids ) throws NamingException
197 {
198 filter( entry );
199
200
201 if ( ids == null )
202 {
203 return;
204 }
205
206
207 if ( dn.size() == 0 )
208 {
209 HashSet idsSet = new HashSet( ids.length );
210
211 for ( int ii = 0; ii < ids.length; ii++ )
212 {
213 idsSet.add( ids[ii].toLowerCase() );
214 }
215
216 NamingEnumeration list = entry.getIDs();
217
218 while ( list.hasMore() )
219 {
220 String attrId = ( ( String ) list.nextElement() ).toLowerCase();
221
222 if ( !idsSet.contains( attrId ) )
223 {
224 entry.remove( attrId );
225 }
226 }
227 }
228
229
230
231
232 }
233
234
235
236
237
238
239
240 public Attributes lookup( NextInterceptor nextInterceptor, Name name ) throws NamingException
241 {
242 Attributes result = nextInterceptor.lookup( name );
243 if ( result == null )
244 {
245 return null;
246 }
247 filter( result );
248 return result;
249 }
250
251
252 public Attributes lookup( NextInterceptor nextInterceptor, Name name, String[] attrIds ) throws NamingException
253 {
254 Attributes result = nextInterceptor.lookup( name, attrIds );
255 if ( result == null )
256 {
257 return null;
258 }
259
260 filter( name, result, attrIds );
261 return result;
262 }
263
264
265 public NamingEnumeration list( NextInterceptor nextInterceptor, Name base ) throws NamingException
266 {
267 NamingEnumeration e = nextInterceptor.list( base );
268 Invocation invocation = InvocationStack.getInstance().peek();
269 return new SearchResultFilteringEnumeration( e, new SearchControls(), invocation, SEARCH_FILTER );
270 }
271
272
273 public NamingEnumeration search( NextInterceptor nextInterceptor,
274 Name base, Map env, ExprNode filter,
275 SearchControls searchCtls ) throws NamingException
276 {
277 NamingEnumeration e = nextInterceptor.search( base, env, filter, searchCtls );
278 Invocation invocation = InvocationStack.getInstance().peek();
279 return new SearchResultFilteringEnumeration( e, searchCtls, invocation, SEARCH_FILTER );
280 }
281 }