1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.exception;
18
19
20 import java.util.Map;
21
22 import javax.naming.Name;
23 import javax.naming.NamingEnumeration;
24 import javax.naming.NamingException;
25 import javax.naming.directory.Attribute;
26 import javax.naming.directory.Attributes;
27 import javax.naming.directory.ModificationItem;
28 import javax.naming.directory.SearchControls;
29
30 import org.apache.ldap.common.exception.LdapContextNotEmptyException;
31 import org.apache.ldap.common.exception.LdapNameAlreadyBoundException;
32 import org.apache.ldap.common.exception.LdapNameNotFoundException;
33 import org.apache.ldap.common.exception.LdapNamingException;
34 import org.apache.ldap.common.filter.ExprNode;
35 import org.apache.ldap.common.message.ResultCodeEnum;
36 import org.apache.ldap.common.name.LdapName;
37 import org.apache.ldap.server.configuration.InterceptorConfiguration;
38 import org.apache.ldap.server.interceptor.BaseInterceptor;
39 import org.apache.ldap.server.interceptor.NextInterceptor;
40 import org.apache.ldap.server.jndi.ContextFactoryConfiguration;
41 import org.apache.ldap.server.partition.ContextPartition;
42
43
44 /***
45 * An {@link org.apache.ldap.server.interceptor.Interceptor} that detects any operations that breaks integrity
46 * of {@link ContextPartition} and terminates the current invocation chain by
47 * throwing a {@link NamingException}. Those operations include when an entry
48 * already exists at a DN and is added once again to the same DN.
49 *
50 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
51 * @version $Rev: 264732 $
52 */
53 public class ExceptionService extends BaseInterceptor
54 {
55 /***
56 * Creates an interceptor that is also the exception handling service.
57 */
58 public ExceptionService()
59 {
60 }
61
62
63 public void init( ContextFactoryConfiguration factoryCfg, InterceptorConfiguration cfg )
64 {
65 }
66
67
68 public void destroy()
69 {
70 }
71
72
73 /***
74 * In the pre-invocation state this interceptor method checks to see if the entry to be added already exists. If it
75 * does an exception is raised.
76 */
77 public void add( NextInterceptor nextInterceptor, String upName, Name normName, Attributes entry ) throws NamingException
78 {
79
80 if ( nextInterceptor.hasEntry( normName ) )
81 {
82 NamingException ne = new LdapNameAlreadyBoundException();
83 ne.setResolvedName( new LdapName( upName ) );
84 throw ne;
85 }
86
87 Name parentDn = new LdapName( upName );
88 parentDn = parentDn.getSuffix( 1 );
89
90
91 assertHasEntry( nextInterceptor, "Attempt to add under non-existant parent: ", parentDn );
92
93
94 Attributes attrs = nextInterceptor.lookup( normName.getSuffix( 1 ) );
95 Attribute objectClass = attrs.get( "objectClass" );
96 if ( objectClass.contains( "alias" ) )
97 {
98 String msg = "Attempt to add entry to alias '" + upName
99 + "' not allowed.";
100 ResultCodeEnum rc = ResultCodeEnum.ALIASPROBLEM;
101 NamingException e = new LdapNamingException( msg, rc );
102 e.setResolvedName( parentDn );
103 throw e;
104 }
105
106 nextInterceptor.add( upName, normName, entry );
107 }
108
109
110 /***
111 * Checks to make sure the entry being deleted exists, and has no children, otherwise throws the appropriate
112 * LdapException.
113 */
114 public void delete( NextInterceptor nextInterceptor, Name name ) throws NamingException
115 {
116
117 String msg = "Attempt to delete non-existant entry: ";
118 assertHasEntry( nextInterceptor, msg, name );
119
120
121 boolean hasChildren = false;
122 NamingEnumeration list = nextInterceptor.list( name );
123 if ( list.hasMore() )
124 {
125 hasChildren = true;
126 }
127
128 list.close();
129 if ( hasChildren )
130 {
131 LdapContextNotEmptyException e = new LdapContextNotEmptyException();
132 e.setResolvedName( name );
133 throw e;
134 }
135
136 nextInterceptor.delete( name );
137 }
138
139
140 /***
141 * Checks to see the base being searched exists, otherwise throws the appropriate LdapException.
142 */
143 public NamingEnumeration list( NextInterceptor nextInterceptor, Name baseName ) throws NamingException
144 {
145
146 String msg = "Attempt to search under non-existant entry: ";
147 assertHasEntry( nextInterceptor, msg, baseName );
148
149 return nextInterceptor.list( baseName );
150 }
151
152
153 /***
154 * Checks to make sure the entry being looked up exists other wise throws the appropriate LdapException.
155 */
156 public Attributes lookup( NextInterceptor nextInterceptor, Name name ) throws NamingException
157 {
158 String msg = "Attempt to lookup non-existant entry: ";
159 assertHasEntry( nextInterceptor, msg, name );
160
161 return nextInterceptor.lookup( name );
162 }
163
164
165 /***
166 * Checks to see the base being searched exists, otherwise throws the appropriate LdapException.
167 */
168 public Attributes lookup( NextInterceptor nextInterceptor, Name name, String[] attrIds ) throws NamingException
169 {
170
171 String msg = "Attempt to lookup non-existant entry: ";
172 assertHasEntry( nextInterceptor, msg, name );
173
174 return nextInterceptor.lookup( name, attrIds );
175 }
176
177
178 /***
179 * Checks to see the entry being modified exists, otherwise throws the appropriate LdapException.
180 */
181 public void modify( NextInterceptor nextInterceptor, Name name, int modOp, Attributes attrs ) throws NamingException
182 {
183
184 String msg = "Attempt to modify non-existant entry: ";
185 assertHasEntry( nextInterceptor, msg, name );
186
187 nextInterceptor.modify( name, modOp, attrs );
188 }
189
190
191 /***
192 * Checks to see the entry being modified exists, otherwise throws the appropriate LdapException.
193 */
194 public void modify( NextInterceptor nextInterceptor, Name name, ModificationItem[] items ) throws NamingException
195 {
196
197 String msg = "Attempt to modify non-existant entry: ";
198 assertHasEntry( nextInterceptor, msg, name );
199
200 nextInterceptor.modify( name, items );
201 }
202
203
204 /***
205 * Checks to see the entry being renamed exists, otherwise throws the appropriate LdapException.
206 */
207 public void modifyRn( NextInterceptor nextInterceptor, Name dn, String newRn, boolean deleteOldRn ) throws NamingException
208 {
209
210 String msg = "Attempt to rename non-existant entry: ";
211 assertHasEntry( nextInterceptor, msg, dn );
212
213
214 Name target = dn.getSuffix( 1 ).add( newRn );
215 if ( nextInterceptor.hasEntry( target ) )
216 {
217 LdapNameAlreadyBoundException e = null;
218 e = new LdapNameAlreadyBoundException( "target entry " + target
219 + " already exists!" );
220 e.setResolvedName( target );
221 throw e;
222 }
223
224 nextInterceptor.modifyRn( dn, newRn, deleteOldRn );
225 }
226
227
228 /***
229 * Checks to see the entry being moved exists, and so does its parent, otherwise throws the appropriate
230 * LdapException.
231 */
232 public void move( NextInterceptor nextInterceptor, Name oriChildName, Name newParentName ) throws NamingException
233 {
234
235 String msg = "Attempt to move to non-existant parent: ";
236 assertHasEntry( nextInterceptor, msg, oriChildName );
237
238
239 msg = "Attempt to move to non-existant parent: ";
240 assertHasEntry( nextInterceptor, msg, newParentName );
241
242
243 String rdn = oriChildName.get( oriChildName.size() - 1 );
244 Name target = ( Name ) newParentName.clone();
245 target.add( rdn );
246 if ( nextInterceptor.hasEntry( target ) )
247 {
248 LdapNameAlreadyBoundException e = null;
249 e = new LdapNameAlreadyBoundException( "target entry " + target
250 + " already exists!" );
251 e.setResolvedName( target );
252 throw e;
253 }
254
255 nextInterceptor.move( oriChildName, newParentName );
256 }
257
258
259 /***
260 * Checks to see the entry being moved exists, and so does its parent, otherwise throws the appropriate
261 * LdapException.
262 */
263 public void move( NextInterceptor nextInterceptor,
264 Name oriChildName, Name newParentName, String newRn,
265 boolean deleteOldRn ) throws NamingException
266 {
267
268 String msg = "Attempt to move to non-existant parent: ";
269 assertHasEntry( nextInterceptor, msg, oriChildName );
270
271
272 msg = "Attempt to move to non-existant parent: ";
273 assertHasEntry( nextInterceptor, msg, newParentName );
274
275
276 Name target = ( Name ) newParentName.clone();
277 target.add( newRn );
278 if ( nextInterceptor.hasEntry( target ) )
279 {
280 LdapNameAlreadyBoundException e = null;
281 e = new LdapNameAlreadyBoundException( "target entry " + target
282 + " already exists!" );
283 e.setResolvedName( target );
284 throw e;
285 }
286
287 nextInterceptor.move( oriChildName, newParentName, newRn, deleteOldRn );
288 }
289
290
291 /***
292 * Checks to see the entry being searched exists, otherwise throws the appropriate LdapException.
293 */
294 public NamingEnumeration search( NextInterceptor nextInterceptor,
295 Name base, Map env, ExprNode filter,
296 SearchControls searchCtls ) throws NamingException
297 {
298 String msg = "Attempt to search under non-existant entry: ";
299
300 if ( base.size() == 0 )
301 {
302 return nextInterceptor.search( base, env, filter, searchCtls );
303 }
304
305 Attribute attr = nextInterceptor.getRootDSE().get( "subschemaSubentry" );
306 if ( ( ( String ) attr.get() ).equalsIgnoreCase( base.toString() ) )
307 {
308 return nextInterceptor.search( base, env, filter, searchCtls );
309 }
310
311 assertHasEntry( nextInterceptor, msg, base );
312
313 return nextInterceptor.search( base, env, filter, searchCtls );
314 }
315
316
317 /***
318 * Asserts that an entry is present and as a side effect if it is not, creates a LdapNameNotFoundException, which is
319 * used to set the before exception on the invocation - eventually the exception is thrown.
320 *
321 * @param msg the message to prefix to the distinguished name for explanation
322 * @param dn the distinguished name of the entry that is asserted
323 * @throws NamingException if the entry does not exist
324 */
325 private void assertHasEntry( NextInterceptor nextInterceptor, String msg, Name dn ) throws NamingException
326 {
327 if ( !nextInterceptor.hasEntry( dn ) )
328 {
329 LdapNameNotFoundException e = null;
330
331 if ( msg != null )
332 {
333 e = new LdapNameNotFoundException( msg + dn );
334 }
335 else
336 {
337 e = new LdapNameNotFoundException( dn.toString() );
338 }
339
340 e.setResolvedName( nextInterceptor.getMatchedName( dn, false ) );
341 throw e;
342 }
343 }
344 }