From 7485b13e7cb0f5ce285c93f7f722ee647e2bd8fd Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Tue, 26 Sep 2023 03:40:39 +0800 Subject: [PATCH] feat: add checking update function --- .../sweet-dependency-config.yaml | 3 + sweetproperty-gradle-plugin/build.gradle.kts | 1 + .../plugin/SweetPropertyExtension.kt | 2 + .../plugin/helper/PluginUpdateHelper.kt | 81 +++++++++++++++++++ .../sweetproperty/utils/HttpFactory.kt | 58 +++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/helper/PluginUpdateHelper.kt create mode 100644 sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/utils/HttpFactory.kt diff --git a/gradle/sweet-dependency/sweet-dependency-config.yaml b/gradle/sweet-dependency/sweet-dependency-config.yaml index c67d0e1..0a32376 100644 --- a/gradle/sweet-dependency/sweet-dependency-config.yaml +++ b/gradle/sweet-dependency/sweet-dependency-config.yaml @@ -18,6 +18,9 @@ plugins: version: 0.25.3 libraries: + com.squareup.okhttp3: + okhttp: + version: 4.11.0 com.squareup: kotlinpoet: version: 1.14.2 diff --git a/sweetproperty-gradle-plugin/build.gradle.kts b/sweetproperty-gradle-plugin/build.gradle.kts index 3e210b5..31b81cd 100644 --- a/sweetproperty-gradle-plugin/build.gradle.kts +++ b/sweetproperty-gradle-plugin/build.gradle.kts @@ -21,6 +21,7 @@ kotlin { } dependencies { + implementation(com.squareup.okhttp3.okhttp) implementation(com.squareup.kotlinpoet) implementation(com.squareup.javapoet) implementation(net.lingala.zip4j.zip4j) diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/SweetPropertyExtension.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/SweetPropertyExtension.kt index 297cb44..a6d6cbb 100644 --- a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/SweetPropertyExtension.kt +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/SweetPropertyExtension.kt @@ -25,6 +25,7 @@ import com.highcapable.sweetproperty.SweetProperty import com.highcapable.sweetproperty.gradle.factory.getOrCreate import com.highcapable.sweetproperty.gradle.proxy.IGradleLifecycle import com.highcapable.sweetproperty.plugin.extension.dsl.configure.SweetPropertyConfigureExtension +import com.highcapable.sweetproperty.plugin.helper.PluginUpdateHelper import com.highcapable.sweetproperty.plugin.helper.PropertiesDeployHelper import com.highcapable.sweetproperty.utils.debug.SError import org.gradle.api.Project @@ -44,6 +45,7 @@ internal class SweetPropertyExtension internal constructor() : IGradleLifecycle override fun onSettingsEvaluate(settings: Settings) { val configs = configure?.build(settings) ?: SError.make("Extension \"${SweetPropertyConfigureExtension.NAME}\" create failed") + PluginUpdateHelper.checkingForUpdate(settings) PropertiesDeployHelper.initialize(settings, configs) } diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/helper/PluginUpdateHelper.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/helper/PluginUpdateHelper.kt new file mode 100644 index 0000000..4696d1c --- /dev/null +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/plugin/helper/PluginUpdateHelper.kt @@ -0,0 +1,81 @@ +/* + * SweetProperty - An easy get project properties anywhere Gradle plugin. + * Copyright (C) 2019-2023 HighCapable + * https://github.com/HighCapable/SweetProperty + * + * Apache License Version 2.0 + * + * 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 + * + * https://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. + * + * This file is created by fankes on 2023/9/26. + */ +package com.highcapable.sweetproperty.plugin.helper + +import com.highcapable.sweetproperty.SweetProperty +import com.highcapable.sweetproperty.generated.SweetPropertyProperties +import com.highcapable.sweetproperty.utils.debug.SLog +import com.highcapable.sweetproperty.utils.executeUrlBody +import org.gradle.api.initialization.Settings +import org.xml.sax.InputSource +import java.io.StringReader +import javax.xml.parsers.DocumentBuilderFactory + +/** + * 插件自身检查更新工具类 + */ +internal object PluginUpdateHelper { + + /** OSS Release URL 地址 */ + private const val SONATYPE_OSS_RELEASES_URL = "https://s01.oss.sonatype.org/content/repositories/releases" + + /** 依赖配置文件名 */ + private const val METADATA_FILE_NAME = "maven-metadata.xml" + + /** 插件自身依赖 URL 名称 */ + private val groupUrlNotation = + "${SweetPropertyProperties.PROJECT_GROUP_NAME.replace(".","/")}/${SweetPropertyProperties.GRADLE_PLUGIN_MODULE_NAME}" + + /** 检查更新 URL 地址 */ + private val releaseUrl = "$SONATYPE_OSS_RELEASES_URL/$groupUrlNotation/$METADATA_FILE_NAME" + + /** + * 检查更新 + * @param settings 当前设置 + */ + internal fun checkingForUpdate(settings: Settings) { + if (settings.gradle.startParameter.isOffline) return + val latestVersion = releaseUrl.executeUrlBody(isShowFailure = false).trim().findLatest() + if (latestVersion.isNotBlank() && latestVersion != SweetProperty.VERSION) SLog.note( + """ + Plugin update is available, the current version is ${SweetProperty.VERSION}, please update to $latestVersion + You can modify your plugin version in your project's settings.gradle / settings.gradle.kts + plugins { + id("${SweetPropertyProperties.PROJECT_GROUP_NAME}") version "$latestVersion" + ... + } + For more information, you can visit ${SweetProperty.PROJECT_URL} + """.trimIndent(), SLog.UP + ) + } + + /** + * 解析 [METADATA_FILE_NAME] 内容并获取 "latest" + * @return [String] + */ + private fun String.findLatest() = runCatching { + if ((contains("")).not() || endsWith("").not()) return@runCatching "" + DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(InputSource(StringReader(this))).let { document -> + document.getElementsByTagName("latest")?.let { if (it.length > 0) it.item(0)?.textContent ?: "" else "" } + } + }.getOrNull() ?: "" +} \ No newline at end of file diff --git a/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/utils/HttpFactory.kt b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/utils/HttpFactory.kt new file mode 100644 index 0000000..e1d29a3 --- /dev/null +++ b/sweetproperty-gradle-plugin/src/main/java/com/highcapable/sweetproperty/utils/HttpFactory.kt @@ -0,0 +1,58 @@ +/* + * SweetProperty - An easy get project properties anywhere Gradle plugin. + * Copyright (C) 2019-2023 HighCapable + * https://github.com/HighCapable/SweetProperty + * + * Apache License Version 2.0 + * + * 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 + * + * https://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. + * + * This file is created by fankes on 2023/9/26. + */ +package com.highcapable.sweetproperty.utils + +import com.highcapable.sweetproperty.utils.debug.SError +import com.highcapable.sweetproperty.utils.debug.SLog +import okhttp3.Credentials +import okhttp3.OkHttpClient +import okhttp3.Request +import java.util.concurrent.TimeUnit + +/** + * 获取当前 URL 地址的请求体字符串内容 (GET) (同步) + * @param username 用户名 + * @param password 密码 + * @param isShowFailure 是否显示错误 - 默认是 + * @return [String] + */ +internal fun String.executeUrlBody(username: String = "", password: String = "", isShowFailure: Boolean = true) = runCatching { + OkHttpClient() + .newBuilder() + .connectTimeout(10000, TimeUnit.MILLISECONDS) + .authenticator { _, response -> + if (response.code == 400 || response.code == 401) + response.request.newBuilder() + .header("Authorization", Credentials.basic(username, password)) + .build() + else null + }.build().newCall( + Request.Builder().url(when { + startsWith("https://") -> "https://" + replace("https://", "").replace("//", "/") + startsWith("http://") -> "http://" + replace("http://", "").replace("//", "/") + else -> SError.make("Invalid URL: $this") + }).get().build() + ).execute().let { + if (it.code == 200 || it.code == 404) it.body?.string() ?: "" + else SError.make("Request failed with code ${it.code}") + } +}.onFailure { if (isShowFailure) SLog.error("Failed to connect to $this\n$it") }.getOrNull() ?: "" \ No newline at end of file