From 25974be3f8c945c08c460bb692b6606a9116af6a Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 15 Jun 2016 23:44:34 +0300 Subject: [PATCH] Provide specialized stdlib function implementations depending on current JRE version #KT-8254 --- .../internal/JRE7PlatformImplementations.kt | 8 +++ .../internal/JRE8PlatformImplementations.kt | 5 ++ .../internal/PlatformImplementations.kt | 56 +++++++++++++++++++ libraries/stdlib/src/kotlin/io/ReadWrite.kt | 16 ++---- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt create mode 100644 libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt create mode 100644 libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt diff --git a/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt new file mode 100644 index 00000000000..4a14282b7c8 --- /dev/null +++ b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt @@ -0,0 +1,8 @@ +package kotlin.internal + +import java.io.Closeable + +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") +internal open class JRE7PlatformImplementations : PlatformImplementations() { + override fun closeSuppressed(instance: Closeable, cause: Throwable) = instance.closeSuppressed(cause) +} diff --git a/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt b/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt new file mode 100644 index 00000000000..bd14b152c0d --- /dev/null +++ b/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt @@ -0,0 +1,5 @@ +package kotlin.internal + +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") +internal open class JRE8PlatformImplementations : JRE7PlatformImplementations() { +} diff --git a/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt new file mode 100644 index 00000000000..1c7cd7158c1 --- /dev/null +++ b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt @@ -0,0 +1,56 @@ +@file:JvmVersion +package kotlin.internal + +import java.io.Closeable + +internal open class PlatformImplementations { + + public open fun closeSuppressed(instance: Closeable, cause: Throwable) { + try { + instance.close() + } catch (closeException: Throwable) { + // eat the closeException as we are already throwing the original cause + // and we don't want to mask the real exception; + // on Java 7 we should call + // e.addSuppressed(closeException) + } + } + + companion object { + @JvmField + @InlineExposed + val INSTANCE: PlatformImplementations = run { + val version = getJavaVersion() + try { + if (version >= 0x10008) + return@run Class.forName("kotlin.internal.JDK8PlatformImplementations").newInstance() as PlatformImplementations + } catch (e: ClassNotFoundException) {} + + try { + if (version >= 0x10007) + return@run Class.forName("kotlin.internal.JDK7PlatformImplementations").newInstance() as PlatformImplementations + } catch (e: ClassNotFoundException) {} + + PlatformImplementations() + } + + private fun getJavaVersion(): Int { + val default = 0x10006 + val version = System.getProperty("java.version") ?: return default + val firstDot = version.indexOf('.') + if (firstDot < 0) return default + var secondDot = version.indexOf('.', firstDot + 1) + if (secondDot < 0) secondDot = version.length + + val firstPart = version.substring(0, firstDot) + val secondPart = version.substring(firstDot + 1, secondDot) + return try { + firstPart.toInt() * 0x10000 + secondPart.toInt() + } catch (e: NumberFormatException) { + default + } + } + + } +} + diff --git a/libraries/stdlib/src/kotlin/io/ReadWrite.kt b/libraries/stdlib/src/kotlin/io/ReadWrite.kt index 61d360ec283..a8948c7dbe9 100644 --- a/libraries/stdlib/src/kotlin/io/ReadWrite.kt +++ b/libraries/stdlib/src/kotlin/io/ReadWrite.kt @@ -6,6 +6,7 @@ import java.io.* import java.nio.charset.Charset import java.net.URL import java.util.NoSuchElementException +import kotlin.internal.PlatformImplementations /** Returns a buffered reader wrapping this Reader, or this Reader itself if it is already buffered. */ @@ -155,19 +156,10 @@ public inline fun T.use(block: (T) -> R): R { var closed = false try { return block(this) - } catch (e: Exception) { + } catch (e: Throwable) { closed = true - try { - close() - } catch (closeException: Exception) { - // eat the closeException as we are already throwing the original cause - // and we don't want to mask the real exception - - // TODO on Java 7 we should call - // e.addSuppressed(closeException) - // to work like try-with-resources - // http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html#suppressed-exceptions - } + @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") + PlatformImplementations.INSTANCE.closeSuppressed(this, e) throw e } finally { if (!closed) {