001: package org.mockejb.jndi;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005:
006: import javax.naming.*;
007: import junit.framework.*;
008:
009: /**
010: * Tests all basic methods of MockContext.
011: * Test for remote context lookup is not included.
012: *
013: * @author Dimitar Gospodinov
014: */
015: public class MockContextTest extends TestCase {
016:
017: private Context initialCtx;
018: private Context compCtx;
019: private Context envCtx;
020: private Context ejbCtx;
021:
022: public MockContextTest(String name) {
023: super (name);
024: }
025:
026: protected void setUp() throws Exception {
027:
028: MockContextFactory.setAsInitial();
029: // Empty initial Context
030: initialCtx = new InitialContext();
031: initialCtx.bind("java:comp/env/ejb/Dummy", null);
032: compCtx = (Context) initialCtx.lookup("java:comp");
033: envCtx = (Context) compCtx.lookup("env");
034: ejbCtx = (Context) envCtx.lookup("ejb");
035: }
036:
037: protected void tearDown() throws Exception {
038:
039: clearContext(initialCtx);
040: ejbCtx = null;
041: envCtx = null;
042: compCtx = null;
043: initialCtx = null;
044: MockContextFactory.revertSetAsInitial();
045: }
046:
047: /**
048: * Removes all entries from the specified context, including subcontexts.
049: * @param context context ot clear
050: */
051: private void clearContext(Context context) throws NamingException {
052:
053: for (NamingEnumeration e = context.listBindings(""); e
054: .hasMoreElements();) {
055: Binding binding = (Binding) e.nextElement();
056: if (binding.getObject() instanceof Context) {
057: clearContext((Context) binding.getObject());
058: }
059: context.unbind(binding.getName());
060: }
061:
062: }
063:
064: /**
065: * Tests inability to create duplicate subcontexts.
066: * @throws NamingException
067: */
068: public void testSubcontextCreationOfDuplicates()
069: throws NamingException {
070:
071: // Try to create duplicate subcontext
072: try {
073: initialCtx.createSubcontext("java:comp");
074: fail();
075: } catch (NameAlreadyBoundException ex) {
076: }
077: // Try to create duplicate subcontext using multi-component name
078: try {
079: compCtx.createSubcontext("env/ejb");
080: fail();
081: } catch (NameAlreadyBoundException ex) {
082: }
083: }
084:
085: /**
086: * Tests inability to destroy non empty subcontexts.
087: * @throws NamingException
088: */
089: public void testSubcontextNonEmptyDestruction()
090: throws NamingException {
091:
092: // Bind some object in ejb subcontext
093: ejbCtx.bind("EmptyTest", "EmptyTest Object");
094: // Attempt to destroy any subcontext
095: try {
096: initialCtx.destroySubcontext("java:comp");
097: fail();
098: } catch (ContextNotEmptyException ex) {
099: }
100: try {
101: initialCtx.destroySubcontext("java:comp/env/ejb");
102: fail();
103: } catch (ContextNotEmptyException ex) {
104: }
105: try {
106: envCtx.destroySubcontext("ejb");
107: fail();
108: } catch (ContextNotEmptyException ex) {
109: }
110: }
111:
112: /**
113: * Tests ability to destroy empty subcontexts.
114: * @throws NamingException
115: */
116: public void testSubcontextDestruction() throws NamingException {
117:
118: // Create three new subcontexts
119: Context sub1 = ejbCtx.createSubcontext("sub1");
120: Context sub2 = ejbCtx.createSubcontext("sub2");
121: Context sub3 = envCtx.createSubcontext("sub3");
122: // Destroy
123: initialCtx.destroySubcontext("java:comp/env/ejb/sub1");
124: ejbCtx.destroySubcontext("sub2");
125: envCtx.destroySubcontext("sub3");
126: // Perform lookup
127: try {
128: ejbCtx.lookup("sub1");
129: fail();
130: } catch (NameNotFoundException ex) {
131: }
132: try {
133: envCtx.lookup("ejb/sub2");
134: fail();
135: } catch (NameNotFoundException ex) {
136: }
137: try {
138: initialCtx.lookup("java:comp/sub3");
139: fail();
140: } catch (NameNotFoundException ex) {
141: }
142: }
143:
144: /**
145: * Tests inability to invoke methods on destroyed subcontexts.
146: * @throws NamingException
147: */
148: public void testSubcontextInvokingMethodsOnDestroyedContext()
149: throws NamingException {
150:
151: //Create subcontext and destroy it.
152: Context sub = ejbCtx.createSubcontext("subXX");
153: initialCtx.destroySubcontext("java:comp/env/ejb/subXX");
154: /*
155: * At this point sub is destroyed. Any method invokation should fail.
156: * Try to bind some object, create subcontext and perform list.
157: * Because the Context was empty, and non-empty Context can not be
158: * destroyed, a lookup will fail and in general may not be tested.
159: * We will test it for completness. The same applies for unbind and destroyContext methods.
160: */
161: try {
162: sub.bind("SomeName", "SomeObject");
163: fail();
164: } catch (NoPermissionException ex) {
165: }
166: try {
167: sub.unbind("SomeName");
168: fail();
169: } catch (NoPermissionException ex) {
170: }
171: try {
172: sub.createSubcontext("SomeSubcontext");
173: fail();
174: } catch (NoPermissionException ex) {
175: }
176: try {
177: sub.destroySubcontext("DummyName");
178: fail();
179: } catch (NoPermissionException ex) {
180: }
181: try {
182: sub.list("");
183: fail();
184: } catch (NoPermissionException ex) {
185: }
186: try {
187: sub.lookup("DummyName");
188: fail();
189: } catch (NoPermissionException ex) {
190: }
191: try {
192: sub.composeName("name", "prefix");
193: fail();
194: } catch (NoPermissionException ex) {
195: }
196: try {
197: MockContextNameParser parser = new MockContextNameParser();
198: sub.composeName(parser.parse("a"), parser.parse("b"));
199: fail();
200: } catch (NoPermissionException ex) {
201: }
202: }
203:
204: /**
205: * Tests ability to bind name to object and inability to bind
206: * duplicate names.
207: * TODO Duplicate names can not be tested at this time because
208: * we treat bind as re-bind.
209: * @throws NamingException
210: */
211: public void testBindLookup() throws NamingException {
212:
213: /*
214: * Add four binding - two for null reference and two for an object,
215: * using atomic and compound names.
216: */
217: Object o1 = new String("Test object for atomic binding");
218: Object o2 = new String("Test object for compound binding");
219: Object o3 = new String(
220: "Test object for complex compound binding");
221: ejbCtx.bind("AtomicNull", null);
222: ejbCtx.bind("AtomicObject", o1);
223: initialCtx.bind("java:comp/env/CompoundNull", null);
224: initialCtx.bind("java:comp/env/CompoundObject", o2);
225: // Bind to subcontexts that do not exist
226: initialCtx.bind(
227: "java:comp/env/ejb/subToCreate1/subToCreate2/oo", o3);
228:
229: // Try to lookup
230: assertNull(ejbCtx.lookup("AtomicNull"));
231: assertSame(ejbCtx.lookup("AtomicObject"), o1);
232: assertNull(compCtx.lookup("env/CompoundNull"));
233: assertSame(initialCtx.lookup("java:comp/env/CompoundObject"),
234: o2);
235: assertSame(ejbCtx.lookup("subToCreate1/subToCreate2/oo"), o3);
236:
237: }
238:
239: /**
240: * Tests ability to unbind names.
241: * @throws NamingException
242: */
243: public void testUnbind() throws NamingException {
244:
245: envCtx.bind("testUnbindName1", null);
246: compCtx.bind("env/ejb/testUnbindName2", new String(
247: "Test unbind object"));
248: // Unbind
249: initialCtx.unbind("java:comp/env/testUnbindName1");
250: ejbCtx.unbind("testUnbindName2");
251: try {
252: envCtx.lookup("testUnbindName1");
253: fail();
254: } catch (NameNotFoundException ex) {
255: }
256: try {
257: initialCtx.lookup("java:comp/env/ejb/testUnbindName2");
258: fail();
259: } catch (NameNotFoundException ex) {
260: }
261: // Unbind non-existing name
262: try {
263: ejbCtx.unbind("This name does not exist in the context");
264: } catch (Exception ex) {
265: fail();
266: }
267: // Unbind non-existing name, when subcontext does not exists
268: try {
269: compCtx.unbind("env/ejb/ejb1/somename");
270: fail();
271: } catch (NameNotFoundException ex) {
272: }
273: }
274:
275: /**
276: * Tests ability to list bindings for a context - specified by
277: * name through object reference.
278: * @throws NamingException
279: */
280: public void testListBindings() throws NamingException {
281:
282: // Add three bindings
283: Object o1 = new String("Test list bindings 1");
284: Object o2 = new String("Test list bindings 2");
285:
286: compCtx.bind("env/ejb/testListBindings1", o1);
287: envCtx.bind("testListBindings2", o2);
288: ejbCtx.bind("testListBindings3", null);
289:
290: // Verify bindings for context specified by reference
291: verifyListBindingsResult(envCtx, "", o1, o2);
292: // Verify bindings for context specified by name
293: verifyListBindingsResult(initialCtx, "java:comp/env", o1, o2);
294: }
295:
296: private void verifyListBindingsResult(Context c, String name,
297: Object o1, Object o2) throws NamingException {
298:
299: boolean ejbFoundFlg = false;
300: boolean o2FoundFlg = false;
301: boolean ejbO1FoundFlg = false;
302: boolean ejbNullFoundFlg = false;
303:
304: // List bindings for the specified context
305: for (NamingEnumeration en = c.listBindings(name); en.hasMore();) {
306: Binding b = (Binding) en.next();
307: if (b.getName().equals("ejb")) {
308: assertEquals(b.getObject(), ejbCtx);
309: ejbFoundFlg = true;
310:
311: Context nextCon = (Context) b.getObject();
312: for (NamingEnumeration en1 = nextCon.listBindings(""); en1
313: .hasMore();) {
314: Binding b1 = (Binding) en1.next();
315: if (b1.getName().equals("testListBindings1")) {
316: assertEquals(b1.getObject(), o1);
317: ejbO1FoundFlg = true;
318: } else if (b1.getName().equals("testListBindings3")) {
319: assertNull(b1.getObject());
320: ejbNullFoundFlg = true;
321: }
322: }
323: } else if (b.getName().equals("testListBindings2")) {
324: assertEquals(b.getObject(), o2);
325: o2FoundFlg = true;
326: }
327: }
328: if (!(ejbFoundFlg && o2FoundFlg && ejbO1FoundFlg && ejbNullFoundFlg)) {
329: fail();
330: }
331: }
332:
333: public void testCompositeNameWithLeadingTrailingEmptyComponents()
334: throws Exception {
335: MockContext c = new MockContext(null);
336: Object o = new Object();
337:
338: c.rebind("/a/b/c/", o);
339: assertEquals(c.lookup("a/b/c"), o);
340: assertEquals(c.lookup("///a/b/c///"), o);
341:
342: }
343:
344: public void testLookup() throws Exception {
345: MockContext mockCtx = new MockContext(null);
346: Object obj = new Object();
347: mockCtx.rebind("a/b/c/d", obj);
348: assertEquals(obj, mockCtx.lookup("a/b/c/d"));
349:
350: mockCtx.bind("a", obj);
351: assertEquals(obj, mockCtx.lookup("a"));
352:
353: }
354:
355: /**
356: * Tests "getCompositeName" method
357: *
358: */
359: public void testGetCompositeName() throws Exception {
360:
361: MockContext mockCtx = new MockContext(null);
362: mockCtx.rebind("a/b/c/d", new Object());
363:
364: MockContext subCtx;
365:
366: subCtx = (MockContext) mockCtx.lookup("a");
367: assertEquals("a", subCtx.getCompoundStringName());
368:
369: subCtx = (MockContext) mockCtx.lookup("a/b/c");
370: assertEquals("a/b/c", subCtx.getCompoundStringName());
371:
372: }
373:
374: /**
375: * Tests that delegate context is
376: * invoked when MockContext does not find the name
377: */
378: public void testDelegateContext() throws Exception {
379:
380: ArrayList recordedLookups = new ArrayList();
381: Context ctx = new MockContext(new RecordingMockContext(
382: recordedLookups));
383:
384: String wrongName;
385:
386: // Test simple name
387: wrongName = "mockejb";
388: ctx.lookup(wrongName);
389: assertEquals(1, recordedLookups.size());
390: assertEquals(wrongName, recordedLookups.get(0));
391:
392: // Test composite name
393: recordedLookups.clear();
394: wrongName = "mockejb/a";
395: ctx.lookup(wrongName);
396: assertEquals(1, recordedLookups.size());
397: assertEquals(wrongName, recordedLookups.get(0));
398:
399: // Test the situation when root context is bound already in MockCOntext
400: recordedLookups.clear();
401: ctx.rebind("mockejb/dummy", new Object());
402: wrongName = "mockejb/a";
403: ctx.lookup(wrongName);
404: assertEquals(1, recordedLookups.size());
405: assertEquals(wrongName, recordedLookups.get(0));
406:
407: }
408:
409: /**
410: * Class to simulate remote context.
411: * always returns the dummy object from lookup
412: * and stores the lookup call info.
413: */
414: class RecordingMockContext extends MockContext {
415:
416: private Collection recordedLookups;
417:
418: public RecordingMockContext(Collection recordedNames) {
419: super (null);
420: this .recordedLookups = recordedNames;
421: }
422:
423: public Object lookup(Name name) throws NamingException {
424: recordedLookups.add(name.toString());
425: return new Object();
426: }
427:
428: public Object lookup(String name) throws NamingException {
429: recordedLookups.add(name);
430: return new Object();
431: }
432:
433: }
434:
435: /**
436: * Tests substitution of '.' with '/' when parsing string names.
437: * @throws NamingException
438: */
439: public void testTwoSeparatorNames() throws NamingException {
440: MockContext ctx = new MockContext(null);
441: Object obj = new Object();
442:
443: ctx.bind("a/b.c.d/e", obj);
444: assertEquals(ctx.lookup("a/b/c/d/e"), obj);
445: assertEquals(ctx.lookup("a.b/c.d.e"), obj);
446: assertTrue(ctx.lookup("a.b.c.d") instanceof Context);
447: }
448:
449: }
|