View Javadoc

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.jndi;
18  
19  import org.apache.ldap.common.filter.ExprNode;
20  import org.apache.ldap.server.BackendSubsystem;
21  import org.apache.ldap.server.ContextPartition;
22  import org.apache.ldap.server.PartitionNexus;
23  import org.apache.ldap.server.RootNexus;
24  import org.apache.ldap.server.interceptor.Interceptor;
25  import org.apache.ldap.server.interceptor.InterceptorChain;
26  import org.apache.ldap.server.invocation.*;
27  
28  import javax.naming.Context;
29  import javax.naming.Name;
30  import javax.naming.NamingEnumeration;
31  import javax.naming.NamingException;
32  import javax.naming.directory.Attributes;
33  import javax.naming.directory.ModificationItem;
34  import javax.naming.directory.SearchControls;
35  import javax.naming.ldap.LdapContext;
36  import java.util.Hashtable;
37  import java.util.Iterator;
38  import java.util.Map;
39  
40  
41  /***
42   * The BackendSubsystem service implementation.
43   * 
44   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
45   * @version $Rev: 159259 $
46   */
47  public class JndiProvider implements BackendSubsystem
48  {
49      /*** Singleton instance of this class */
50      private static JndiProvider s_singleton;
51      
52      /*** The interceptor (or interceptor chain) for this provider */
53      private Interceptor interceptor;
54      /*** RootNexus as it was given to us by the ServiceManager */
55      private RootNexus nexus;
56      /*** PartitionNexus proxy wrapping nexus to inject services */
57      private PartitionNexus proxy;
58  
59      /*** whether or not this instance has been shutdown */
60      private boolean isShutdown = false;
61  
62  
63      // ------------------------------------------------------------------------
64      // Constructor
65      // ------------------------------------------------------------------------
66  
67  
68      /***
69       * Creates a singlton instance of the BackendSubsystem.  In the words of
70       * the Highlander, "there can only be one."
71       *
72       * @throws IllegalStateException if another JndiProvider has already
73       * been instantiated.
74       */
75      public JndiProvider( RootNexus nexus )
76      {
77          if ( s_singleton != null )
78          {
79              throw new IllegalStateException(
80                  "Cannot instantiate more than one JndiProvider!" );
81          }
82  
83          s_singleton = this;
84          this.nexus = nexus;
85          this.interceptor = new InterceptorChain();
86          this.proxy = new PartitionNexusImpl();
87      }
88  
89  
90      // ------------------------------------------------------------------------
91      // Static Package Friendly Methods
92      // ------------------------------------------------------------------------
93  
94  
95      /***
96       * Enables a ServerContextFactory with a handle to the system wide
97       * JndiProvider instance.
98       *
99       * @param factory the ServerContextFactory to enable
100      */
101     static void setProviderOn( CoreContextFactory factory )
102     {
103         factory.setProvider( s_singleton );
104     }
105 
106 
107     // ------------------------------------------------------------------------
108     // BackendSubsystem Interface Method Implemetations
109     // ------------------------------------------------------------------------
110 
111 
112     /***
113      * @see org.apache.ldap.server.BackendSubsystem#getLdapContext(Hashtable)
114      */
115     public LdapContext getLdapContext( Hashtable env ) throws NamingException
116     {
117         if ( this.isShutdown )
118         {
119             throw new IllegalStateException( "Eve has been shutdown!" );
120         }
121 
122         return new ServerLdapContext( proxy, env );
123     }
124 
125 
126     public void sync() throws NamingException
127     {
128         if ( this.isShutdown )
129         {
130             throw new IllegalStateException( "Eve has been shutdown!" );
131         }
132 
133         this.nexus.sync();
134     }
135 
136 
137     public void shutdown() throws NamingException
138     {
139         if ( this.isShutdown )
140         {
141             throw new IllegalStateException( "Eve has been shutdown!" );
142         }
143 
144         this.nexus.sync();
145         this.nexus.close();
146         this.nexus = null;
147         this.proxy = null;
148         this.interceptor.destroy();
149         this.interceptor = null;
150         this.isShutdown = true;
151         s_singleton = null;
152     }
153     
154     public Interceptor getInterceptor()
155     {
156         return interceptor;
157     }
158 
159     public void setInterceptor( Interceptor interceptor )
160     {
161         if( interceptor == null )
162         {
163             throw new NullPointerException( "interceptor" );
164         }
165         this.interceptor = interceptor;
166     }
167 
168 
169     public Object invoke( Invocation call ) throws NamingException
170     {
171         interceptor.process( null, call );
172         return call.getReturnValue();
173     }
174 
175     /***
176      * A dead context is requested and returned when we shutdown the system. It
177      * prevents a {@link javax.naming.NoInitialContextException} from being
178      * thrown by InitialContext or one of its subclasses.
179      *
180      * @return a unusable dead context
181      */
182     public Context getDeadContext()
183     {
184         return new DeadContext();
185     }
186     
187     private class PartitionNexusImpl implements PartitionNexus
188     {
189 
190         public LdapContext getLdapContext() {
191             return nexus.getLdapContext();
192         }
193 
194         public Name getMatchedDn(Name dn, boolean normalized) throws NamingException {
195             return ( Name ) JndiProvider.this.invoke( new GetMatchedDN( dn, normalized ) );
196         }
197 
198         public Name getSuffix(Name dn, boolean normalized) throws NamingException {
199             return ( Name ) JndiProvider.this.invoke( new GetSuffix( dn, normalized ) );
200         }
201 
202         public Iterator listSuffixes(boolean normalized) throws NamingException {
203             return ( Iterator ) JndiProvider.this.invoke( new ListSuffixes( normalized ) );
204         }
205 
206         public void register(ContextPartition partition) {
207             nexus.register( partition );
208         }
209 
210         public void unregister(ContextPartition partition) {
211             nexus.unregister( partition );
212         }
213 
214         public void delete(Name name) throws NamingException {
215             JndiProvider.this.invoke( new Delete( name ) );
216         }
217 
218         public void add(String upName, Name normName, Attributes entry) throws NamingException {
219             JndiProvider.this.invoke( new Add( upName, normName, entry ) );
220         }
221 
222         public void modify(Name name, int modOp, Attributes mods) throws NamingException {
223             JndiProvider.this.invoke( new Modify( name, modOp, mods ) );
224         }
225 
226         public void modify(Name name, ModificationItem[] mods) throws NamingException {
227             JndiProvider.this.invoke( new ModifyMany( name, mods ) );
228         }
229 
230         public NamingEnumeration list(Name base) throws NamingException {
231             return ( NamingEnumeration ) JndiProvider.this.invoke( new List( base ) );
232         }
233 
234         public NamingEnumeration search(Name base, Map env, ExprNode filter, SearchControls searchCtls) throws NamingException {
235             return ( NamingEnumeration ) JndiProvider.this.invoke( new Search( base, env, filter, searchCtls ) );
236         }
237 
238         public Attributes lookup(Name name) throws NamingException {
239             return ( Attributes ) JndiProvider.this.invoke( new Lookup( name ) );
240         }
241 
242         public Attributes lookup(Name dn, String[] attrIds) throws NamingException {
243             return ( Attributes ) JndiProvider.this.invoke( new LookupWithAttrIds( dn, attrIds ) );
244         }
245 
246         public boolean hasEntry(Name name) throws NamingException {
247             return Boolean.TRUE.equals( JndiProvider.this.invoke( new HasEntry( name ) ) );
248         }
249 
250         public boolean isSuffix(Name name) throws NamingException {
251             return Boolean.TRUE.equals( JndiProvider.this.invoke( new IsSuffix( name ) ) );
252         }
253 
254         public void modifyRn(Name name, String newRn, boolean deleteOldRn) throws NamingException {
255             JndiProvider.this.invoke( new ModifyRN( name, newRn, deleteOldRn ) );
256         }
257 
258         public void move(Name oriChildName, Name newParentName) throws NamingException {
259             JndiProvider.this.invoke( new Move( oriChildName, newParentName ) );
260         }
261 
262         public void move(Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn) throws NamingException {
263             JndiProvider.this.invoke( new MoveAndModifyRN( oriChildName, newParentName, newRn, deleteOldRn ) );
264         }
265 
266         public void sync() throws NamingException {
267             nexus.sync();
268         }
269 
270         public void close() throws NamingException {
271             nexus.close();
272         }
273 
274         public boolean isClosed() {
275             return nexus.isClosed();
276         }
277         
278     }
279 }