From 0cf1c8d9006b8dac972865d1ecc133cae7ac9b9c Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Mon, 11 Apr 2016 21:50:21 +0300 Subject: [PATCH] Workaround for building against jars from both JDK 6 and JDK 8 on TeamCity --- .../kotlin/jps/bothJdkClasspathPatcher.kt | 47 +++++++++++++++++++ .../jps/build/AbstractIncrementalJpsTest.kt | 5 ++ .../build/AbstractKotlinJpsBuildTestCase.java | 5 ++ 3 files changed, 57 insertions(+) create mode 100644 jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/bothJdkClasspathPatcher.kt diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/bothJdkClasspathPatcher.kt b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/bothJdkClasspathPatcher.kt new file mode 100644 index 00000000000..b45e10ff664 --- /dev/null +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/bothJdkClasspathPatcher.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * 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.jetbrains.kotlin.jps + +import org.jetbrains.jps.cmdline.ClasspathBootstrap +import java.lang.reflect.Field +import java.lang.reflect.Modifier + +fun disableJava6FileManager() { + val fileManagerClass = ClasspathBootstrap.getOptimizedFileManagerClass() + if (fileManagerClass?.simpleName == "OptimizedFileManager") { + // JPS tests depends on idea.jar and can't be executed under Java 1.6 anymore. But currently TeamCity merges classpath from all + // dependencies in a one big mess with no differences between JDK and non-JDK jars. Such behaviour causes both + // JDK 8 and JDK 6 classes present in classpath. Next there's ClasspathBootstrap.OptimizedFileManagerClassHolder in idea + // that works through reflection and tries to choose correct FileManager that are not the same in JDK 6 and JDK 8. Choosing + // FileManager for JDK 6 leads to exceptions on Runtime as classes from JDK 8 goes first on teamcity. + // + // Here we disable JDK 6 FileManager with brute force. + val clazz = Class.forName("org.jetbrains.jps.cmdline.ClasspathBootstrap\$OptimizedFileManagerClassHolder") + setFinalStaticToNull(clazz.getDeclaredField("managerClass")) + setFinalStaticToNull(clazz.getDeclaredField("directoryCacheClearMethod")) + } +} + +private fun setFinalStaticToNull(field: Field) { + field.isAccessible = true; + + val modifiersField = (Field::class.java).getDeclaredField("modifiers") + modifiersField.isAccessible = true + modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv()) + + field.set(null, null) +} diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt index 641dc532c0f..9f6d141a814 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.incremental.CacheVersion import org.jetbrains.kotlin.incremental.LookupSymbol import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.testingUtils.* +import org.jetbrains.kotlin.jps.disableJava6FileManager import org.jetbrains.kotlin.jps.incremental.JpsLookupStorageProvider import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget import org.jetbrains.kotlin.jps.incremental.getKotlinCache @@ -65,6 +66,10 @@ abstract class AbstractIncrementalJpsTest( private val allowNoBuildLogFileInTestData: Boolean = false ) : JpsBuildTestCase() { companion object { + init { + disableJava6FileManager() + } + private val COMPILATION_FAILED = "COMPILATION FAILED" // change to "/tmp" or anything when default is too long (for easier debugging) diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractKotlinJpsBuildTestCase.java b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractKotlinJpsBuildTestCase.java index ede371c900a..0d24ce77667 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractKotlinJpsBuildTestCase.java +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/AbstractKotlinJpsBuildTestCase.java @@ -31,6 +31,7 @@ import org.jetbrains.jps.model.library.JpsTypedLibrary; import org.jetbrains.jps.model.library.sdk.JpsSdk; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.util.JpsPathUtil; +import org.jetbrains.kotlin.jps.BothJdkClasspathPatcherKt; import org.jetbrains.kotlin.utils.PathUtil; import java.io.File; @@ -40,6 +41,10 @@ import java.util.Collection; public abstract class AbstractKotlinJpsBuildTestCase extends JpsBuildTestCase { public static final String TEST_DATA_PATH = "jps-plugin/testData/"; + static { + BothJdkClasspathPatcherKt.disableJava6FileManager(); + } + protected File workDir; @Override