blob: 6d3be4566e3dc796f8d02499edeb47f6b7748068 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.core.ivm.naming;
import junit.framework.TestCase;
import org.apache.openejb.util.Debug;
import org.apache.openejb.util.Join;
import javax.naming.Context;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import javax.naming.OperationNotSupportedException;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.SystemException;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
/**
* @version $Rev$ $Date$
*/
public class IvmContextTest extends TestCase {
private Map<String, Integer> map;
private IvmContext context;
public void testLookups() throws Exception {
// lookup
for (final Map.Entry<String, Integer> entry : map.entrySet()) {
final String name = entry.getKey();
final Integer expected = entry.getValue();
visit(context, name, new Visitor() {
public void visit(final Context context, final String name, final String parentName) throws NamingException {
assertLookup("relative lookup " + parentName + " : " + name, context, name, expected);
}
});
}
}
public void testList() throws Exception {
// list
for (final Map.Entry<String, Integer> entry : map.entrySet()) {
final String name = entry.getKey();
visit(context, name, new Visitor() {
public void visit(final Context context, final String name, final String parentName) throws NamingException {
final Map<String, Object> expected = new TreeMap<>();
for (final Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
if (key.startsWith(parentName)) {
key = key.substring(parentName.length(), key.length());
expected.put(key, entry.getValue());
}
}
final Map<String, Object> actual = list(context);
assertEquals("relative list " + parentName + " : " + name, expected, actual);
}
});
}
}
public void setUp() throws Exception {
map = new LinkedHashMap<>();
map.put("color/orange", 1);
map.put("color/blue", 2);
map.put("color/red/scarlet", 3);
map.put("color/red/crimson", 4);
map.put("shape", 5);
context = new IvmContext("/");
for (final Map.Entry<String, Integer> entry : map.entrySet()) {
context.bind(entry.getKey(), entry.getValue());
}
}
private Map<String, Object> list(final Context context) throws NamingException {
final Map<String, Object> map = Debug.contextToMap(context);
// Prune the context entries out
map.entrySet().removeIf(entry -> entry.getValue() instanceof Context);
return map;
}
private void assertLookup(final String message, final Context context, final String name, final Object expected) {
try {
final Object actual = context.lookup(name);
assertNotNull(message, actual);
assertEquals(message, expected, actual);
} catch (final NamingException e) {
fail(message + " - Exception:" + e.getClass().getName() + " : " + e.getMessage());
}
}
public void test1() throws Exception {
final IvmContext context = new IvmContext("");
context.bind("one", 1);
context.bind("two", 2);
context.bind("three", 3);
assertContextEntry(context, "one", 1);
assertContextEntry(context, "two", 2);
assertContextEntry(context, "three", 3);
context.unbind("one");
try {
context.lookup("one");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException e) {
// pass
}
// The other entries should still be there
// assertContextEntry(context, "one", 1);
assertContextEntry(context, "two", 2);
assertContextEntry(context, "three", 3);
final Map<String, Object> map = list(context);
assertFalse("name should not appear in bindings list", map.containsKey("one"));
}
public void test2() throws Exception {
final IvmContext context = new IvmContext();
context.bind("one", 1);
context.bind("two", 2);
context.bind("three", 3);
assertContextEntry(context, "one", 1);
assertContextEntry(context, "two", 2);
assertContextEntry(context, "three", 3);
context.unbind("two");
try {
context.lookup("two");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException e) {
// pass
}
// The other entries should still be there
assertContextEntry(context, "one", 1);
assertContextEntry(context, "three", 3);
final Map<String, Object> map = list(context);
assertFalse("name should not appear in bindings list", map.containsKey("two"));
}
public void test3() throws Exception {
final IvmContext context = new IvmContext();
context.bind("veggies/tomato/roma", 33);
context.bind("fruit/apple/grannysmith", 22);
context.bind("fruit/orange/mandarin", 44);
assertContextEntry(context, "veggies/tomato/roma", 33);
assertContextEntry(context, "fruit/apple/grannysmith", 22);
assertContextEntry(context, "fruit/orange/mandarin", 44);
context.unbind("fruit/apple/grannysmith");
context.prune("fruit");
context.unbind("veggies/tomato/roma");
context.prune("veggies");
try {
context.lookup("fruit/apple/grannysmith");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException pass) {
}
try {
context.lookup("veggies/tomato/roma");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException pass) {
}
try {
context.lookup("veggies/tomato");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException pass) {
}
try {
context.lookup("veggies/fruit");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException pass) {
}
final Map<String, Object> map = list(context);
assertFalse("name should not appear in bindings list", map.containsKey("veggies/tomato/roma"));
}
public void testAlreadyBound() throws Exception {
final IvmContext context = new IvmContext();
context.bind("number", 2);
try {
context.bind("number", 3);
fail("A NameAlreadyBoundException should have been thrown");
} catch (final NameAlreadyBoundException e) {
// pass
}
}
public void test() throws Exception {
final IvmContext context = new IvmContext();
context.bind("comp/env/rate/work/doc/lot/pop", 1);
context.bind("comp/env/rate/work/doc/lot/price", 2);
context.bind("comp/env/rate/work/doc/lot/break/story", 3);
final Object o = context.lookup("comp/env/rate/work/doc/lot/pop");
assertNotNull(o);
assertTrue(o instanceof Integer);
assertEquals(o, 1);
context.unbind("comp/env/rate/work/doc/lot/pop");
try {
context.lookup("comp/env/rate/work/doc/lot/pop");
fail("name should be unbound");
} catch (final javax.naming.NameNotFoundException e) {
// pass
}
final Map<String, Object> map = list(context);
assertFalse("name should not appear in bindings list", map.containsKey("comp/env/rate/work/doc/lot/pop"));
}
public void testReadOnlyThrowsExceptionByDefault() throws NamingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final IvmContext context = new IvmContext();
context.setReadOnly(true);
try {
context.bind("global/foo/Bar", "Bar");
fail();
} catch (OperationNotSupportedException e) {
// ok
}
}
public void testReadOnlyNoException() throws NamingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final IvmContext context = new IvmContext();
context.setReadOnly(true);
String originalValue = System.getProperty(IvmContext.JNDI_EXCEPTION_ON_FAILED_WRITE);
System.setProperty(IvmContext.JNDI_EXCEPTION_ON_FAILED_WRITE, Boolean.FALSE.toString());
try {
Context subContext = context.createSubcontext("global/foo/Bar");
assertNull(subContext);
} finally {
if(originalValue == null) {
System.clearProperty(IvmContext.JNDI_EXCEPTION_ON_FAILED_WRITE);
} else {
System.setProperty(IvmContext.JNDI_EXCEPTION_ON_FAILED_WRITE, originalValue);
}
SystemInstance.reset();
}
}
public void testReadOnlyAppliedRecursively() throws NamingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final IvmContext context = new IvmContext();
Context subContext = context.createSubcontext("global/foo/Bar");
context.setReadOnly(true);
if(IvmContext.class.isInstance(subContext)) {
assertTrue(IvmContext.class.cast(subContext).readOnly);
} else {
throw new IllegalStateException("Naming context " + subContext + " not instance of " + IvmContext.class) ;
}
}
/*
* NameNode#getBinding returns new IvmContext wrapping current read-only context in some cases
* This test checks whether the "wrapper" is also read only if the current is
*/
public void testGetBindingPropagatesReadOnlyFlag() throws NamingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final IvmContext context = new IvmContext("comp");
context.bind("env/test", "test");
context.setReadOnly(true);
Object result = context.lookup("env");
if(IvmContext.class.isInstance(result)) {
assertTrue(IvmContext.class.cast(result).readOnly);
} else {
throw new IllegalStateException("Naming context " + result + " not instance of " + IvmContext.class) ;
}
}
/*
* NameNode#resolve returns new IvmContext wrapping current read-only context on lookup of name bound only in federated context
* This test checks whether the "wrapper" is also read only if the current is
*/
public void testGetFromFederatedContextPropagatesReadOnlyFlag() throws NamingException {
final IvmContext context = new IvmContext();
final IvmContext federatedContext = new IvmContext("comp");
federatedContext.bind("env/test", "test");
context.bind("", federatedContext);
context.setReadOnly(true);
Object result = context.lookup("env");
if(IvmContext.class.isInstance(result)) {
assertTrue(IvmContext.class.cast(result).readOnly);
} else {
throw new IllegalStateException("Naming context " + result + " not instance of " + IvmContext.class) ;
}
}
public void testCloseNoExceptionByDefault() throws NamingException {
final IvmContext context = new IvmContext();
try {
context.close();
} catch (OperationNotSupportedException e) {
fail();
}
}
public void testCloseDoesNotThrowExceptionIfReadOnly() throws NamingException {
final IvmContext context = new IvmContext();
context.setReadOnly(true);
try {
context.close();
//ok
} catch (OperationNotSupportedException e) {
fail();
}
}
public void testListContextListsAllFederatedContextBindings() throws SystemException, NamingException {
//mimic logic from EnterpriseBeanBuilder.build, create compJndiContext and bind in it module, app, global
Context compContext = new IvmContext();
compContext.bind("java:comp/env/dummy", "dummy");
Context moduleContext = new IvmContext();
moduleContext.bind("module/env/test", String.class);
moduleContext.bind("module/env/sub/test2", String.class);
Context originalModuleSubContext = (IvmContext)moduleContext.lookup("module");
compContext.bind("module", originalModuleSubContext);
Context referencedModuleEnvSubContext = (IvmContext)compContext.lookup("module/env");
NamingEnumeration<NameClassPair> referencedEnvLookupResult = referencedModuleEnvSubContext.list("");
boolean testFound= false;
boolean subFound = false;
while(referencedEnvLookupResult.hasMore()) {
String currentName = referencedEnvLookupResult.next().getName();
if("test".equals(currentName)) {
testFound = true;
} else if("sub".equals(currentName)) {
subFound = true;
} else {
fail();
}
}
assertTrue(testFound);
assertTrue(subFound);
}
private void assertContextEntry(final Context context, final String s, final Object expected) throws javax.naming.NamingException {
assertLookup(context, s, expected);
}
public interface Visitor {
public void visit(Context context, String name, String parentName) throws NamingException;
}
private void visit(final Context context, final String name, final Visitor visitor) throws NamingException {
visit(context, name, "", visitor);
}
private void visit(final Context context, final String name, final String parentName, final Visitor visitor) throws NamingException {
visitor.visit(context, name, parentName);
final String[] parts = name.split("/");
if (parts.length > 1) {
final String thisPart = parts[0];
final Object o = context.lookup(thisPart);
assertNotNull(o);
assertTrue(o instanceof Context);
visit((Context) o, subpath(parts), parentName + thisPart + "/", visitor);
}
}
private void _visit(final Context context, final String name, final Object expected) throws NamingException {
// bind
// try {
// context.bind(s, expected);
// fail("should not be allowed to bind");
// } catch (NameAlreadyBoundException e) {
// // pass
// }
// rebind
// String tmp = expected.toString() + System.currentTimeMillis();
// context.rebind(s, tmp);
// assertLookup(context, s, tmp);
// unbind
// context.unbind(s);
// try {
// context.lookup(s);
// fail("name should be unbound");
// } catch (NameNotFoundException e) {
// // pass
// }
// Restore the original state
// context.bind(s, expected);
// assertLookup(context, s, expected);
}
private void assertLookup(final Context context, final String s, final Object expected) throws NamingException {
final Object actual = context.lookup(s);
assertNotNull(actual);
assertEquals(expected, actual);
}
private String subpath(final String[] strings) {
final String[] strings2 = new String[strings.length - 1];
System.arraycopy(strings, 1, strings2, 0, strings2.length);
final String path = Join.join("/", strings2);
return path;
}
}