KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ldap > server > schema > SchemaService


1 /*
2  * Copyright 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.ldap.server.schema;
18
19
20 import org.apache.ldap.common.filter.ExprNode;
21 import org.apache.ldap.common.filter.PresenceNode;
22 import org.apache.ldap.common.filter.SimpleNode;
23 import org.apache.ldap.common.message.LockableAttributeImpl;
24 import org.apache.ldap.common.message.LockableAttributesImpl;
25 import org.apache.ldap.common.name.LdapName;
26 import org.apache.ldap.common.schema.*;
27 import org.apache.ldap.common.util.SingletonEnumeration;
28 import org.apache.ldap.server.RootNexus;
29 import org.apache.ldap.server.interceptor.BaseInterceptor;
30 import org.apache.ldap.server.interceptor.InterceptorContext;
31 import org.apache.ldap.server.interceptor.NextInterceptor;
32 import org.apache.ldap.server.db.ResultFilteringEnumeration;
33 import org.apache.ldap.server.db.SearchResultFilter;
34 import org.apache.ldap.server.invocation.List;
35 import org.apache.ldap.server.invocation.Lookup;
36 import org.apache.ldap.server.invocation.LookupWithAttrIds;
37 import org.apache.ldap.server.invocation.Search;
38 import org.apache.ldap.server.jndi.ServerLdapContext;
39 import org.apache.ldap.server.schema.AttributeTypeRegistry;
40 import org.apache.ldap.server.schema.GlobalRegistries;
41
42 import javax.naming.NamingEnumeration JavaDoc;
43 import javax.naming.NamingException JavaDoc;
44 import javax.naming.directory.Attribute JavaDoc;
45 import javax.naming.directory.Attributes JavaDoc;
46 import javax.naming.directory.SearchControls JavaDoc;
47 import javax.naming.directory.SearchResult JavaDoc;
48 import javax.naming.ldap.LdapContext JavaDoc;
49 import java.util.Collections JavaDoc;
50 import java.util.HashSet JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.Set JavaDoc;
53
54
55 /**
56  * An {@link org.apache.ldap.server.interceptor.Interceptor} that manages and enforces schemas.
57  *
58  * @todo Better interceptor description required.
59  * @author <a HREF="mailto:dev@directory.apache.org">Apache Directory Project</a>
60  * @version $Rev: 169198 $, $Date: 2005-05-08 20:05:59 -0400 (Sun, 08 May 2005) $
61  */

62 public class SchemaService extends BaseInterceptor
63 {
64     private static final String JavaDoc BINARY_KEY = "java.naming.ldap.attributes.binary";
65
66     /**
67      * the root nexus to all database partitions
68      */

69     private RootNexus nexus;
70
71     /**
72      * a binary attribute tranforming filter: String -> byte[]
73      */

74     private BinaryAttributeFilter binaryAttributeFilter;
75
76     /**
77      * the global schema object registries
78      */

79     private GlobalRegistries globalRegistries;
80
81     private AttributeTypeRegistry attributeRegistry;
82
83     /**
84      * subschemaSubentry attribute's value from Root DSE
85      */

86     private String JavaDoc subentryDn;
87
88
89     /**
90      * Creates a schema service interceptor.
91      */

92     public SchemaService()
93     {
94     }
95
96
97     public void init( InterceptorContext ctx ) throws NamingException JavaDoc
98     {
99         this.nexus = ctx.getRootNexus();
100         this.globalRegistries = ctx.getGlobalRegistries();
101         attributeRegistry = globalRegistries.getAttributeTypeRegistry();
102         binaryAttributeFilter = new BinaryAttributeFilter();
103
104         // stuff for dealing with subentries (garbage for now)
105
String JavaDoc subschemaSubentry = ( String JavaDoc ) nexus.getRootDSE().get( "subschemaSubentry" ).get();
106         subentryDn = new LdapName( subschemaSubentry ).toString().toLowerCase();
107     }
108
109
110     public void destroy()
111     {
112     }
113
114
115     protected void process( NextInterceptor nextInterceptor, List call ) throws NamingException JavaDoc
116     {
117         nextInterceptor.process( call );
118
119         NamingEnumeration JavaDoc e;
120         ResultFilteringEnumeration retval;
121         LdapContext ctx = ( LdapContext ) call.getContextStack().peek();
122         e = ( NamingEnumeration JavaDoc ) call.getReturnValue();
123         retval = new ResultFilteringEnumeration( e, new SearchControls JavaDoc(), ctx, binaryAttributeFilter );
124         call.setReturnValue( retval );
125     }
126
127
128     protected void process( NextInterceptor nextInterceptor, Search call ) throws NamingException JavaDoc
129     {
130         // check to make sure the DN searched for is a subentry
131
if ( !subentryDn.equals( call.getBaseName().toString() ) )
132         {
133             nextInterceptor.process( call );
134             return;
135         }
136
137         boolean bypass = false;
138         SearchControls JavaDoc searchControls = call.getControls();
139         ExprNode filter = call.getFilter();
140         if ( searchControls.getSearchScope() == SearchControls.OBJECT_SCOPE &&
141                 filter instanceof SimpleNode )
142         {
143             SimpleNode node = ( SimpleNode ) filter;
144
145             if ( node.getAttribute().equalsIgnoreCase( "objectClass" ) &&
146                     node.getValue().equalsIgnoreCase( "subschema" ) &&
147                     node.getAssertionType() == SimpleNode.EQUALITY
148             )
149             {
150                 // call.setBypass( true );
151
Attributes JavaDoc attrs = getSubschemaEntry( searchControls.getReturningAttributes() );
152                 SearchResult JavaDoc result = new SearchResult JavaDoc( call.getBaseName().toString(), null, attrs );
153                 SingletonEnumeration e = new SingletonEnumeration( result );
154                 call.setReturnValue( e );
155                 bypass = true;
156             }
157         }
158         else if ( searchControls.getSearchScope() == SearchControls.OBJECT_SCOPE &&
159                 filter instanceof PresenceNode )
160         {
161             PresenceNode node = ( PresenceNode ) filter;
162
163             if ( node.getAttribute().equalsIgnoreCase( "objectClass" ) )
164             {
165                 // call.setBypass( true );
166
Attributes JavaDoc attrs = getSubschemaEntry( searchControls.getReturningAttributes() );
167                 SearchResult JavaDoc result = new SearchResult JavaDoc( call.getBaseName().toString(), null, attrs );
168                 SingletonEnumeration e = new SingletonEnumeration( result );
169                 call.setReturnValue( e );
170                 bypass = true;
171             }
172         }
173
174         if ( !bypass )
175         {
176             nextInterceptor.process( call );
177         }
178
179         if ( searchControls.getReturningAttributes() != null )
180         {
181             return;
182         }
183
184         NamingEnumeration JavaDoc e;
185         ResultFilteringEnumeration retval;
186         LdapContext ctx = ( LdapContext ) call.getContextStack().peek();
187         e = ( NamingEnumeration JavaDoc ) call.getReturnValue();
188         retval = new ResultFilteringEnumeration( e, searchControls, ctx, binaryAttributeFilter );
189         call.setReturnValue( retval );
190     }
191
192
193     private Attributes JavaDoc getSubschemaEntry( String JavaDoc[] ids ) throws NamingException JavaDoc
194     {
195         if ( ids == null )
196         {
197             return new LockableAttributesImpl();
198         }
199
200         HashSet JavaDoc set = new HashSet JavaDoc( ids.length );
201         LockableAttributesImpl attrs = new LockableAttributesImpl();
202         LockableAttributeImpl attr = null;
203
204         for ( int ii = 0; ii < ids.length; ii++ )
205         {
206             set.add( ids[ii].toLowerCase() );
207         }
208
209
210         if ( set.contains( "objectclasses" ) )
211         {
212             attr = new LockableAttributeImpl( attrs, "objectClasses" );
213             Iterator JavaDoc list = globalRegistries.getObjectClassRegistry().list();
214             while ( list.hasNext() )
215             {
216                 ObjectClass oc = ( ObjectClass ) list.next();
217                 attr.add( SchemaUtils.render( oc ).toString() );
218             }
219             attrs.put( attr );
220         }
221
222         if ( set.contains( "attributetypes" ) )
223         {
224             attr = new LockableAttributeImpl( attrs, "attributeTypes" );
225             Iterator JavaDoc list = globalRegistries.getAttributeTypeRegistry().list();
226             while ( list.hasNext() )
227             {
228                 AttributeType at = ( AttributeType ) list.next();
229                 attr.add( SchemaUtils.render( at ).toString() );
230             }
231             attrs.put( attr );
232         }
233
234         if ( set.contains( "matchingrules" ) )
235         {
236             attr = new LockableAttributeImpl( attrs, "matchingRules" );
237             Iterator JavaDoc list = globalRegistries.getMatchingRuleRegistry().list();
238             while ( list.hasNext() )
239             {
240                 MatchingRule mr = ( MatchingRule ) list.next();
241                 attr.add( SchemaUtils.render( mr ).toString() );
242             }
243             attrs.put( attr );
244         }
245
246         if ( set.contains( "matchingruleuse" ) )
247         {
248             attr = new LockableAttributeImpl( attrs, "matchingRuleUse" );
249             Iterator JavaDoc list = globalRegistries.getMatchingRuleUseRegistry().list();
250             while ( list.hasNext() )
251             {
252                 MatchingRuleUse mru = ( MatchingRuleUse ) list.next();
253                 attr.add( SchemaUtils.render( mru ).toString() );
254             }
255             attrs.put( attr );
256         }
257
258         if ( set.contains( "ldapsyntaxes" ) )
259         {
260             attr = new LockableAttributeImpl( attrs, "ldapSyntaxes" );
261             Iterator JavaDoc list = globalRegistries.getSyntaxRegistry().list();
262             while ( list.hasNext() )
263             {
264                 Syntax syntax = ( Syntax ) list.next();
265                 attr.add( SchemaUtils.render( syntax ).toString() );
266             }
267             attrs.put( attr );
268         }
269
270         if ( set.contains( "ditcontentrules" ) )
271         {
272             attr = new LockableAttributeImpl( attrs, "dITContentRules" );
273             Iterator JavaDoc list = globalRegistries.getDitContentRuleRegistry().list();
274             while ( list.hasNext() )
275             {
276                 DITContentRule dcr = ( DITContentRule ) list.next();
277                 attr.add( SchemaUtils.render( dcr ).toString() );
278             }
279             attrs.put( attr );
280         }
281
282         if ( set.contains( "ditstructurerules" ) )
283         {
284             attr = new LockableAttributeImpl( attrs, "dITStructureRules" );
285             Iterator JavaDoc list = globalRegistries.getDitStructureRuleRegistry().list();
286             while ( list.hasNext() )
287             {
288                 DITStructureRule dsr = ( DITStructureRule ) list.next();
289                 attr.add( SchemaUtils.render( dsr ).toString() );
290             }
291             attrs.put( attr );
292         }
293
294         if ( set.contains( "nameforms" ) )
295         {
296             attr = new LockableAttributeImpl( attrs, "nameForms" );
297             Iterator JavaDoc list = globalRegistries.getNameFormRegistry().list();
298             while ( list.hasNext() )
299             {
300                 NameForm nf = ( NameForm ) list.next();
301                 attr.add( SchemaUtils.render( nf ).toString() );
302             }
303             attrs.put( attr );
304         }
305
306         // add the objectClass attribute
307
attr = new LockableAttributeImpl( attrs, "objectClass" );
308         attr.add( "top" );
309         attr.add( "subschema" );
310         attrs.put( attr );
311
312         // add the cn attribute as required for the RDN
313
attrs.put( "cn", "schema" );
314
315         return attrs;
316     }
317
318
319     protected void process( NextInterceptor nextInterceptor, Lookup call ) throws NamingException JavaDoc
320     {
321         nextInterceptor.process( call );
322
323         ServerLdapContext ctx = ( ServerLdapContext ) call.getContextStack().peek();
324         Attributes JavaDoc attributes = ( Attributes JavaDoc ) call.getReturnValue();
325         Attributes JavaDoc retval = ( Attributes JavaDoc ) attributes.clone();
326         doFilter( ctx, retval );
327         call.setReturnValue( retval );
328     }
329
330
331     protected void process( NextInterceptor nextInterceptor, LookupWithAttrIds call ) throws NamingException JavaDoc
332     {
333         nextInterceptor.process( call );
334
335         ServerLdapContext ctx = ( ServerLdapContext ) call.getContextStack().peek();
336         Attributes JavaDoc attributes = ( Attributes JavaDoc ) call.getReturnValue();
337         if ( attributes == null )
338         {
339             return;
340         }
341
342         Attributes JavaDoc retval = ( Attributes JavaDoc ) attributes.clone();
343         doFilter( ctx, retval );
344         call.setReturnValue( retval );
345     }
346
347
348     private void doFilter( LdapContext ctx, Attributes JavaDoc entry )
349             throws NamingException JavaDoc
350     {
351         // set of AttributeType objects that are to behave as binaries
352
Set JavaDoc binaries;
353         
354         // construct the set for fast lookups while filtering
355
String JavaDoc binaryIds = ( String JavaDoc ) ctx.getEnvironment().get( BINARY_KEY );
356
357         if ( binaryIds == null )
358         {
359             binaries = Collections.EMPTY_SET;
360         }
361         else
362         {
363             String JavaDoc[] binaryArray = binaryIds.split( " " );
364
365             binaries = new HashSet JavaDoc( binaryArray.length );
366
367             for ( int ii = 0; ii < binaryArray.length; ii++ )
368             {
369                 AttributeType type = attributeRegistry.lookup( binaryArray[ii] );
370
371                 binaries.add( type );
372             }
373         }
374         
375         /*
376          * start converting values of attributes to byte[]s which are not
377          * human readable and those that are in the binaries set
378          */

379         NamingEnumeration JavaDoc list = entry.getIDs();
380
381         while ( list.hasMore() )
382         {
383             String JavaDoc id = ( String JavaDoc ) list.next();
384
385             AttributeType type = null;
386
387             boolean asBinary = false;
388
389             if ( attributeRegistry.hasAttributeType( id ) )
390             {
391                 type = attributeRegistry.lookup( id );
392             }
393
394             if ( type != null )
395             {
396                 asBinary = !type.getSyntax().isHumanReadible();
397
398                 asBinary = asBinary || binaries.contains( type );
399             }
400
401             if ( asBinary )
402             {
403                 Attribute JavaDoc attribute = entry.get( id );
404
405                 Attribute JavaDoc binary = new LockableAttributeImpl( id );
406
407                 for ( int ii = 0; ii < attribute.size(); ii++ )
408                 {
409                     Object JavaDoc value = attribute.get( ii );
410
411                     if ( value instanceof String JavaDoc )
412                     {
413                         binary.add( ii, ( ( String JavaDoc ) value ).getBytes() );
414                     }
415                     else
416                     {
417                         binary.add( ii, value );
418                     }
419                 }
420
421                 entry.remove( id );
422
423                 entry.put( binary );
424             }
425         }
426     }
427
428
429     /**
430      * A special filter over entry attributes which replaces Attribute String values with their respective byte[]
431      * representations using schema information and the value held in the JNDI environment property:
432      * <code>java.naming.ldap.attributes.binary</code>.
433      *
434      * @see <a HREF= "http://java.sun.com/j2se/1.4.2/docs/guide/jndi/jndi-ldap-gl.html#binary">
435      * java.naming.ldap.attributes.binary</a>
436      */

437     private class BinaryAttributeFilter implements SearchResultFilter
438     {
439         public BinaryAttributeFilter()
440         {
441         }
442
443
444         public boolean accept( LdapContext ctx, SearchResult JavaDoc result, SearchControls JavaDoc controls ) throws NamingException JavaDoc
445         {
446             doFilter( ctx, result.getAttributes() );
447             return true;
448         }
449     }
450 }
451
Popular Tags