View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.core.jndi;
21  
22  
23  import java.util.Hashtable;
24  
25  import javax.naming.NamingException;
26  import javax.naming.ldap.Control;
27  import javax.naming.ldap.ExtendedRequest;
28  import javax.naming.ldap.ExtendedResponse;
29  import javax.naming.ldap.LdapContext;
30  
31  import org.apache.directory.server.core.CoreSession;
32  import org.apache.directory.server.core.DirectoryService;
33  import org.apache.directory.server.core.authn.LdapPrincipal;
34  import org.apache.directory.server.core.entry.ServerBinaryValue;
35  import org.apache.directory.server.core.entry.ServerStringValue;
36  import org.apache.directory.server.core.interceptor.context.CompareOperationContext;
37  import org.apache.directory.server.core.interceptor.context.UnbindOperationContext;
38  import org.apache.directory.shared.ldap.NotImplementedException;
39  import org.apache.directory.shared.ldap.entry.Value;
40  import org.apache.directory.shared.ldap.name.LdapDN;
41  import org.apache.directory.shared.ldap.schema.AttributeType;
42  import org.apache.directory.shared.ldap.util.StringTools;
43  
44  
45  /**
46   * An implementation of a JNDI LdapContext.
47   *
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   * @version $Rev: 680867 $
50   */
51  public class ServerLdapContext extends ServerDirContext implements LdapContext
52  {
53      /**
54       * Creates an instance of an ServerLdapContext.
55       *
56       * @param service the parent service that manages this context
57       * @param env the JNDI environment parameters
58       * @throws NamingException the context cannot be created
59       */
60      public ServerLdapContext( DirectoryService service, Hashtable<String, Object> env ) throws Exception
61      {
62          super( service, env );
63      }
64  
65  
66      /**
67       * Creates a new ServerDirContext with a distinguished name which is used to
68       * set the PROVIDER_URL to the distinguished name for this context.
69       *
70       * @param principal the directory user principal that is propagated
71       * @param dn the distinguished name of this context
72       * @param service the directory service core
73       * @throws NamingException if there are problems instantiating 
74       */
75      public ServerLdapContext( DirectoryService service, LdapPrincipal principal, LdapDN dn ) throws Exception
76      {
77          super( service, principal, dn );
78      }
79  
80  
81      public ServerLdapContext( DirectoryService service, CoreSession session, LdapDN bindDn ) throws Exception
82      {
83          super( service, session, bindDn );
84      }
85  
86  
87      /**
88       * @see javax.naming.ldap.LdapContext#extendedOperation(
89       * javax.naming.ldap.ExtendedRequest)
90       */
91      public ExtendedResponse extendedOperation( ExtendedRequest request )
92      {
93          throw new NotImplementedException();
94      }
95  
96  
97      /**
98       * @see javax.naming.ldap.LdapContext#newInstance(
99       * javax.naming.ldap.Control[])
100      */
101     public LdapContext newInstance( Control[] requestControls ) throws NamingException
102     {
103         ServerLdapContext ctx = null;
104         try
105         {
106             ctx = new ServerLdapContext( getService(), getSession().getEffectivePrincipal(), ( LdapDN ) getDn() );
107         }
108         catch ( Exception e )
109         {
110             JndiUtils.wrap( e );
111         }
112         ctx.setRequestControls( requestControls );
113         return ctx;
114     }
115 
116 
117     /**
118      * @see javax.naming.ldap.LdapContext#reconnect(javax.naming.ldap.Control[])
119      */
120     public void reconnect( Control[] connCtls ) throws NamingException
121     {
122         this.connectControls = connCtls;
123     }
124 
125 
126     /**
127      * @see javax.naming.ldap.LdapContext#getConnectControls()
128      */
129     public Control[] getConnectControls() throws NamingException
130     {
131         return this.connectControls;
132     }
133 
134 
135     /**
136      * @see javax.naming.ldap.LdapContext#setRequestControls(
137      * javax.naming.ldap.Control[])
138      */
139     public void setRequestControls( Control[] requestControls ) throws NamingException
140     {
141         this.requestControls = requestControls;
142     }
143 
144 
145     /**
146      * @see javax.naming.ldap.LdapContext#getRequestControls()
147      */
148     public Control[] getRequestControls() throws NamingException
149     {
150         return requestControls;
151     }
152 
153 
154     /**
155      * @see javax.naming.ldap.LdapContext#getResponseControls()
156      */
157     public Control[] getResponseControls() throws NamingException
158     {
159         return responseControls;
160     }
161 
162 
163     // ------------------------------------------------------------------------
164     // Additional ApacheDS Specific JNDI Functionality
165     // ------------------------------------------------------------------------
166 
167     /**
168      * Explicitly exposes an LDAP compare operation which JNDI does not
169      * directly provide.  All normalization and schema checking etcetera
170      * is handled by this call.
171      *
172      * @param name the name of the entri
173      * @param oid the name or object identifier for the attribute to compare
174      * @param value the value to compare the attribute to
175      * @return true if the entry has the value for the attribute, false otherwise
176      * @throws NamingException if the backing store cannot be accessed, or
177      * permission is not allowed for this operation or the oid is not recognized,
178      * or the attribute is not present in the entry ... you get the picture.
179      */
180     public boolean compare( LdapDN name, String oid, Object value ) throws NamingException
181     {
182         Value<?> val = null;
183         
184         AttributeType attributeType = getService().getRegistries().getAttributeTypeRegistry().lookup( oid );
185         
186         // make sure we add the request controls to operation
187         if ( attributeType.getSyntax().isHumanReadable() )
188         {
189             if ( value instanceof String )
190             {
191                 val = new ServerStringValue( attributeType, (String)value );
192             }
193             else if ( value instanceof byte[] )
194             {
195                 val = new ServerStringValue( attributeType, StringTools.utf8ToString( (byte[])value ) );
196             }
197             else
198             {
199                 throw new NamingException( "Bad value for the OID " + oid );
200             }
201         }
202         else
203         {
204             if ( value instanceof String )
205             {
206                 val = new ServerBinaryValue( attributeType, StringTools.getBytesUtf8( (String)value ) );
207             }
208             else if ( value instanceof byte[] )
209             {
210                 val = new ServerBinaryValue( attributeType, (byte[])value );
211             }
212             else
213             {
214                 throw new NamingException( "Bad value for the OID " + oid );
215             }
216         }
217         
218         
219         CompareOperationContext opCtx = new CompareOperationContext( getSession(), name, oid, val );
220         opCtx.addRequestControls( requestControls );
221 
222         // execute operation
223         boolean result = false;
224         try
225         {
226             result = super.getDirectoryService().getOperationManager().compare( opCtx );
227         }
228         catch ( Exception e )
229         {
230             JndiUtils.wrap( e );
231         }
232         
233         // extract the response controls from the operation and return
234         responseControls = getResponseControls();
235         requestControls = EMPTY_CONTROLS;
236         return result;
237     }
238 
239 
240     /**
241      * Calling this method tunnels an unbind call down into the partition holding 
242      * the bindDn.  The bind() counter part is not exposed because it is automatically
243      * called when you create a new initial context for a new connection (on wire) or 
244      * (programatic) caller.
245      * 
246      * @throws NamingException if there are failures encountered while unbinding
247      */
248     public void ldapUnbind() throws NamingException
249     {
250         LdapDN principalDn = getSession().getEffectivePrincipal().getJndiName();
251         UnbindOperationContext opCtx = new UnbindOperationContext( getSession() );
252         opCtx.addRequestControls( requestControls );
253         try
254         {
255             super.getDirectoryService().getOperationManager().unbind( opCtx );
256         }
257         catch ( Exception e )
258         {
259             JndiUtils.wrap( e );
260         }
261         responseControls = opCtx.getResponseControls();
262         requestControls = EMPTY_CONTROLS;
263     }
264 
265 
266     public ServerContext getRootContext() throws NamingException
267     {
268         ServerContext ctx = null;
269         
270         try
271         {
272             ctx = new ServerLdapContext( getService(), getSession().getEffectivePrincipal(), new LdapDN() );
273         }
274         catch ( Exception e )
275         {
276             JndiUtils.wrap( e );
277         }
278         
279         return ctx;
280     }
281 }