1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
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
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 }