Skip to content

Commit

Permalink
Fix NPE in case the resource is AutoClosable and can be null (#287)
Browse files Browse the repository at this point in the history
* Fix exception for resources that can be null

* Update version

* Add test for null auto-closable resource
  • Loading branch information
OptimumCode authored Jan 17, 2024
1 parent acddb48 commit 681e43e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
release_version=5.7.2
release_version=5.7.3
description='th2 common library (Java)'
vcs_url=https://github.com/th2-net/th2-common-j
kapt.include.compile.classpath=false
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import com.exactpro.th2.common.schema.factory.LazyProvider.ThrowableConsumer
import java.util.concurrent.Callable
import java.util.concurrent.atomic.AtomicReference

internal class LazyProvider<T : Any?> private constructor(
/**
* This is class is for internal use only. Please, keep that in mind when using it in another module
*/
// Kotlin internal keyword does not help here because you can still access the class from Java
class LazyProvider<T : Any?> private constructor(
private val name: String,
private val supplier: Callable<out T>,
private val onClose: ThrowableConsumer<in T>
Expand Down Expand Up @@ -48,7 +52,9 @@ internal class LazyProvider<T : Any?> private constructor(
return if (reference.compareAndSet(null, State.Init)) {
val holder = State.Hold(initialize())
if (!reference.compareAndSet(State.Init, holder)) {
onClose.consume(holder.value)
if (holder.value != null) {
onClose.consume(holder.value)
}
error("provider '$name' already closed")
}
holder
Expand All @@ -70,7 +76,7 @@ internal class LazyProvider<T : Any?> private constructor(
}

val prevState = reference.getAndSet(State.Closed)
if (prevState is State.Hold) {
if (prevState is State.Hold && prevState.value != null) {
onClose.consume(prevState.value)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2024 Exactpro (Exactpro Systems Limited)
*
* 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 com.exactpro.th2.common.schema.factory;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class LazyProviderJavaTest {
@Test
void nullAutoClosable() {
LazyProvider<AutoCloseable> provider = LazyProvider.lazyAutocloseable("test", () -> null);
var resource = provider.get();
Assertions.assertNull(resource, "unexpected resource value");
Assertions.assertDoesNotThrow(provider::close, "unexpected error when closing resource");
}
}

0 comments on commit 681e43e

Please sign in to comment.