Skip to content

Commit

Permalink
Fix VerifyError while loading configuration on legacy Android versions
Browse files Browse the repository at this point in the history
  • Loading branch information
pmwmedia committed Jun 25, 2022
1 parent 7ca7089 commit caebd10
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2022 Martin Winandy
*
* Licensed 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.tinylog.configuration;

import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.tinylog.Level;
import org.tinylog.provider.InternalLogger;

/**
* Wrapper for {@link InitialContext} for preventing {@link java.lang.VerifyError} on legacy Android versions.
*/
final class InitialContextWrapper {

/** */
private InitialContextWrapper() {
}

/**
* Looks up the textual value for a given name from {@link InitialContext} without throwing any
* {@link NamingException}.
*
* @param name The name for the expected value
* @return The stored textual value or {@code null} if none found
*/
static String resolve(final String name) {
try {
Object value = InitialContext.doLookup(name);
return value == null ? null : value.toString();
} catch (NameNotFoundException ex) {
return null;
} catch (NamingException ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to look up \"" + name + "\"");
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@

package org.tinylog.configuration;

import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.tinylog.Level;
import org.tinylog.provider.InternalLogger;

/**
* Resolver for JNDI values.
*/
Expand Down Expand Up @@ -49,16 +42,7 @@ public char getPrefix() {
@Override
public String resolve(final String name) {
String fullName = name.contains(":") ? name : DEFAULT_PREFIX + name;

try {
Object value = InitialContext.doLookup(fullName);
return value == null ? null : value.toString();
} catch (NameNotFoundException ex) {
return null;
} catch (NamingException ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to look up \"" + fullName + "\"");
return null;
}
return InitialContextWrapper.resolve(fullName);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2022 Martin Winandy
*
* Licensed 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.tinylog.configuration;

import javax.naming.InitialContext;
import javax.naming.InvalidNameException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.tinylog.rules.SystemStreamCollector;

import static org.assertj.core.api.Assertions.assertThat;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

/**
* Tests for {@link InitialContextWrapper}.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(InitialContext.class)
public class InitialContextWrapperTest {

/**
* Redirects and collects system output streams.
*/
@Rule
public final SystemStreamCollector systemStream = new SystemStreamCollector(true);

/**
* Initialize mocking of {@link InitialContext}.
*/
@Before
public void init() {
mockStatic(InitialContext.class);
}

/**
* Verifies that the String value of a JNDI name can be resolved.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveJndiStringValue() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenReturn("bar");
assertThat(InitialContextWrapper.resolve("java:comp/env/foo")).isEqualTo("bar");
}

/**
* Verifies that the {@code null} value of a JNDI name can be resolved.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveJndiNullValue() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenReturn(null);
assertThat(InitialContextWrapper.resolve("java:comp/env/foo")).isNull();
}

/**
* Verifies that {@code null} is returned for a non-existent JNDI name.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveMissingJndiName() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenThrow(NameNotFoundException.class);
assertThat(InitialContextWrapper.resolve("java:comp/env/foo")).isNull();
}

/**
* Verifies that {@code null} is returned and an error is logged, if the {@link InitialContext} throws any kind of
* {@link NamingException} during lookup.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void failResolvingInvalidJndiName() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenThrow(InvalidNameException.class);
assertThat(InitialContextWrapper.resolve("java:comp/env/foo")).isNull();
assertThat(systemStream.consumeErrorOutput())
.contains(InvalidNameException.class.getName(), "java:comp/env/foo");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@
package org.tinylog.configuration;

import javax.naming.InitialContext;
import javax.naming.InvalidNameException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.tinylog.rules.SystemStreamCollector;

import static org.assertj.core.api.Assertions.assertThat;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
Expand All @@ -39,12 +35,6 @@ public final class JndiValueResolverTest {

private static final JndiValueResolver resolver = JndiValueResolver.INSTANCE;

/**
* Redirects and collects system output streams.
*/
@Rule
public final SystemStreamCollector systemStream = new SystemStreamCollector(true);

/**
* Initialize mocking of {@link InitialContext}.
*/
Expand All @@ -53,7 +43,6 @@ public void init() {
mockStatic(InitialContext.class);
}


/**
* Verifies the name of the resolver.
*/
Expand All @@ -71,54 +60,28 @@ public void prefix() {
}

/**
* Verifies that the String value of a JNDI name can be resolved.
* Verifies that the String value of a JNDI name can be resolved by providing the full JNDI name.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveJndiStringValue() throws NamingException {
public void resolveWithPrefix() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenReturn("bar");
assertThat(resolver.resolve("foo")).isEqualTo("bar");
assertThat(resolver.resolve("java:comp/env/foo")).isEqualTo("bar");
}

/**
* Verifies that the {@code null} value of a JNDI name can be resolved.
* Verifies that the String value of a JNDI name can be resolved by providing the JNDI name without the default
* prefix.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveJndiNullValue() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenReturn(null);
assertThat(resolver.resolve("foo")).isNull();
}

/**
* Verifies that {@code null} is returned for a non-existent JNDI name.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void resolveMissingJndiName() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenThrow(NameNotFoundException.class);
assertThat(resolver.resolve("foo")).isNull();
}

/**
* Verifies that {@code null} is returned and an error is logged, if the {@link InitialContext} throws any kind of
* {@link NamingException} during lookup.
*
* @throws NamingException
* Failed mocking JNDI lookup
*/
@Test
public void failResolvingInvalidJndiName() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenThrow(InvalidNameException.class);
assertThat(resolver.resolve("foo")).isNull();
assertThat(systemStream.consumeErrorOutput())
.contains(InvalidNameException.class.getName(), "java:comp/env/foo");
public void resolveWithoutPrefix() throws NamingException {
when(InitialContext.doLookup("java:comp/env/foo")).thenReturn("bar");
assertThat(resolver.resolve("foo")).isEqualTo("bar");
}

}

0 comments on commit caebd10

Please sign in to comment.