|
17 | 17 | package org.jetbrains.kotlin.utils
|
18 | 18 |
|
19 | 19 | import com.intellij.openapi.diagnostic.Logger
|
20 |
| -import com.intellij.openapi.util.io.FileUtil |
21 | 20 | import com.intellij.openapi.vfs.VirtualFile
|
22 |
| -import com.intellij.util.Processor |
23 |
| -import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull |
24 | 21 | import java.io.*
|
25 |
| -import java.util.Properties |
| 22 | +import java.util.* |
26 | 23 | import java.util.jar.Attributes
|
27 | 24 | import java.util.jar.JarFile
|
28 | 25 | import java.util.jar.Manifest
|
29 |
| -import java.util.zip.ZipFile |
30 | 26 |
|
31 | 27 | object LibraryUtils {
|
32 | 28 | private val LOG = Logger.getInstance(LibraryUtils::class.java)
|
33 | 29 |
|
34 | 30 | val KOTLIN_JS_MODULE_NAME: String = "Kotlin-JS-Module-Name"
|
35 | 31 | private var TITLE_KOTLIN_JAVASCRIPT_STDLIB: String
|
36 | 32 | private var TITLE_KOTLIN_JAVASCRIPT_LIB: String
|
37 |
| - private val METAINF = "META-INF/" |
38 |
| - private val MANIFEST_PATH = "${METAINF}MANIFEST.MF" |
39 |
| - private val METAINF_RESOURCES = "${METAINF}resources/" |
| 33 | + |
| 34 | + val META_INF = "META-INF/" |
| 35 | + private val MANIFEST_PATH = "${META_INF}MANIFEST.MF" |
40 | 36 | private val KOTLIN_JS_MODULE_ATTRIBUTE_NAME = Attributes.Name(KOTLIN_JS_MODULE_NAME)
|
41 | 37 |
|
42 | 38 | init {
|
@@ -73,128 +69,20 @@ object LibraryUtils {
|
73 | 69 | }
|
74 | 70 |
|
75 | 71 | @JvmStatic fun isOldKotlinJavascriptLibrary(library: File): Boolean =
|
76 |
| - checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_LIB, Attributes.Name.SPECIFICATION_TITLE) && getKotlinJsModuleName(library) != null |
| 72 | + checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_LIB, Attributes.Name.SPECIFICATION_TITLE) && |
| 73 | + getKotlinJsModuleName(library) != null |
77 | 74 |
|
78 |
| - @JvmStatic fun isKotlinJavascriptLibraryWithMetadata(library: File): Boolean = KotlinJavascriptMetadataUtils.loadMetadata(library).isNotEmpty() |
| 75 | + @JvmStatic fun isKotlinJavascriptLibraryWithMetadata(library: File): Boolean = |
| 76 | + KotlinJavascriptMetadataUtils.loadMetadata(library).isNotEmpty() |
79 | 77 |
|
| 78 | + @Suppress("unused") // used in K2JSCompilerMojo |
80 | 79 | @JvmStatic fun isKotlinJavascriptLibrary(library: File): Boolean =
|
81 | 80 | isOldKotlinJavascriptLibrary(library) || isKotlinJavascriptLibraryWithMetadata(library)
|
82 | 81 |
|
83 | 82 | @JvmStatic fun isKotlinJavascriptStdLibrary(library: File): Boolean {
|
84 | 83 | return checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_STDLIB, Attributes.Name.IMPLEMENTATION_TITLE)
|
85 | 84 | }
|
86 | 85 |
|
87 |
| - @JvmStatic fun copyJsFilesFromLibraries(libraries: List<String>, outputLibraryJsPath: String) { |
88 |
| - for (library in libraries) { |
89 |
| - val file = File(library) |
90 |
| - assert(file.exists()) { "Library " + library + " not found" } |
91 |
| - |
92 |
| - if (file.isDirectory) { |
93 |
| - copyJsFilesFromDirectory(file, outputLibraryJsPath) |
94 |
| - } |
95 |
| - else { |
96 |
| - copyJsFilesFromZip(file, outputLibraryJsPath) |
97 |
| - } |
98 |
| - } |
99 |
| - } |
100 |
| - |
101 |
| - @JvmStatic fun traverseJsLibraries(libs: List<File>, action: (content: String, path: String)->Unit) { |
102 |
| - libs.forEach { traverseJsLibrary(it, action) } |
103 |
| - } |
104 |
| - |
105 |
| - @JvmStatic fun traverseJsLibrary(lib: File, action: (content: String, path: String)->Unit) { |
106 |
| - when { |
107 |
| - lib.isDirectory -> traverseDirectory(lib, action) |
108 |
| - FileUtil.isJarOrZip(lib) -> traverseArchive(lib, action) |
109 |
| - lib.name.endsWith(KotlinJavascriptMetadataUtils.JS_EXT) -> { |
110 |
| - lib.runIfFileExists(action) |
111 |
| - val jsFile = lib.withReplacedExtensionOrNull(KotlinJavascriptMetadataUtils.META_JS_SUFFIX, KotlinJavascriptMetadataUtils.JS_EXT) |
112 |
| - jsFile?.runIfFileExists(action) |
113 |
| - } |
114 |
| - else -> |
115 |
| - throw IllegalArgumentException("Unknown library format (directory, zip or js file expected): $lib") |
116 |
| - } |
117 |
| - } |
118 |
| - |
119 |
| - private fun File.runIfFileExists(action: (content: String, path: String)->Unit) { |
120 |
| - if (isFile) { |
121 |
| - action(FileUtil.loadFile(this), "") |
122 |
| - } |
123 |
| - } |
124 |
| - |
125 |
| - private fun copyJsFilesFromDirectory(dir: File, outputLibraryJsPath: String) { |
126 |
| - traverseDirectory(dir) { |
127 |
| - content, relativePath -> FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content) |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - private fun processDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) { |
132 |
| - FileUtil.processFilesRecursively(dir, object : Processor<File> { |
133 |
| - override fun process(file: File): Boolean { |
134 |
| - val relativePath = FileUtil.getRelativePath(dir, file) ?: throw IllegalArgumentException("relativePath should not be null " + dir + " " + file) |
135 |
| - if (file.isFile && relativePath.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) { |
136 |
| - val suggestedRelativePath = getSuggestedPath(relativePath) |
137 |
| - if (suggestedRelativePath == null) return true |
138 |
| - |
139 |
| - action(FileUtil.loadFile(file), suggestedRelativePath) |
140 |
| - } |
141 |
| - return true |
142 |
| - } |
143 |
| - }) |
144 |
| - } |
145 |
| - |
146 |
| - fun traverseDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) { |
147 |
| - try { |
148 |
| - processDirectory(dir, action) |
149 |
| - } |
150 |
| - catch (ex: IOException) { |
151 |
| - LOG.error("Could not read files from directory ${dir.name}: ${ex.message}") |
152 |
| - } |
153 |
| - } |
154 |
| - |
155 |
| - private fun copyJsFilesFromZip(file: File, outputLibraryJsPath: String) { |
156 |
| - traverseArchive(file) { content, relativePath -> |
157 |
| - FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content) |
158 |
| - } |
159 |
| - } |
160 |
| - |
161 |
| - fun traverseArchive(file: File, action: (content: String, relativePath: String) -> Unit) { |
162 |
| - val zipFile = ZipFile(file.path) |
163 |
| - try { |
164 |
| - val zipEntries = zipFile.entries() |
165 |
| - while (zipEntries.hasMoreElements()) { |
166 |
| - val entry = zipEntries.nextElement() |
167 |
| - val entryName = entry.name |
168 |
| - if (!entry.isDirectory && entryName.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) { |
169 |
| - val relativePath = getSuggestedPath(entryName) |
170 |
| - if (relativePath == null) continue |
171 |
| - |
172 |
| - val stream = zipFile.getInputStream(entry) |
173 |
| - val content = FileUtil.loadTextAndClose(stream) |
174 |
| - action(content, relativePath) |
175 |
| - } |
176 |
| - } |
177 |
| - } |
178 |
| - catch (ex: IOException) { |
179 |
| - LOG.error("Could not extract files from archive ${file.name}: ${ex.message}") |
180 |
| - } |
181 |
| - finally { |
182 |
| - zipFile.close() |
183 |
| - } |
184 |
| - } |
185 |
| - |
186 |
| - private fun getSuggestedPath(path: String): String? { |
187 |
| - val systemIndependentPath = FileUtil.toSystemIndependentName(path) |
188 |
| - if (systemIndependentPath.startsWith(METAINF)) { |
189 |
| - if (systemIndependentPath.startsWith(METAINF_RESOURCES)) { |
190 |
| - return path.substring(METAINF_RESOURCES.length) |
191 |
| - } |
192 |
| - return null |
193 |
| - } |
194 |
| - |
195 |
| - return path |
196 |
| - } |
197 |
| - |
198 | 86 | private fun getManifestFromJar(library: File): Manifest? {
|
199 | 87 | if (!library.canRead()) return null
|
200 | 88 |
|
|
0 commit comments