blob: f8e3a21e64519edbedba359430d6c9bb0874ad7d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.streampark.common.util
import org.apache.commons.lang3.StringUtils
import java.io._
import java.net.{HttpURLConnection, URL}
import java.time.{Duration, LocalDateTime}
import java.util.{jar, Collection => JavaCollection, Map => JavaMap, Properties, UUID}
import java.util.concurrent.locks.LockSupport
import java.util.jar.{JarFile, JarInputStream}
import scala.annotation.tailrec
import scala.collection.convert.ImplicitConversions._
import scala.util.{Failure, Success, Try}
object Utils extends Logger {
private[this] lazy val OS = System.getProperty("os.name").toLowerCase
def requireNotNull(obj: Any, message: String): Unit = {
if (obj == null) {
throw new NullPointerException(message)
}
}
def requireNotNull(obj: Any): Unit = {
requireNotNull(obj, "this argument must not be null")
}
def requireNotEmpty(elem: Any): Boolean = {
elem match {
case null => false
case x if x.isInstanceOf[Array[_]] => elem.asInstanceOf[Array[_]].nonEmpty
case x if x.isInstanceOf[CharSequence] => elem.toString.trim.nonEmpty
case x if x.isInstanceOf[Traversable[_]] => x.asInstanceOf[Traversable[_]].nonEmpty
case x if x.isInstanceOf[Iterable[_]] => x.asInstanceOf[Iterable[_]].nonEmpty
case x if x.isInstanceOf[JavaCollection[_]] => !x.asInstanceOf[JavaCollection[_]].isEmpty
case x if x.isInstanceOf[JavaMap[_, _]] => !x.asInstanceOf[JavaMap[_, _]].isEmpty
case _ => true
}
}
def isEmpty(elem: Any): Boolean = !requireNotEmpty(elem)
def required(expression: Boolean): Unit = {
if (!expression) {
throw new IllegalArgumentException
}
}
def required(expression: Boolean, errorMessage: Any): Unit = {
if (!expression) {
throw new IllegalArgumentException(s"Requirement failed: ${errorMessage.toString}")
}
}
def uuid(): String = UUID.randomUUID().toString.replaceAll("-", "")
@throws[IOException]
def requireCheckJarFile(jar: URL): Unit = {
val jarFile: File = Try(new File(jar.toURI)) match {
case Success(x) => x
case Failure(_) => throw new IOException(s"JAR file path is invalid $jar")
}
if (!jarFile.exists) {
throw new IOException(s"JAR file does not exist '${jarFile.getAbsolutePath}'")
}
if (!jarFile.canRead) {
throw new IOException(s"JAR file can't be read '${jarFile.getAbsolutePath}'")
}
Try(new JarFile(jarFile)) match {
case Failure(e) =>
throw new IOException(s"Error while opening jar file '${jarFile.getAbsolutePath}'", e)
case Success(x) => x.close()
}
}
def getJarManifest(jarFile: File): jar.Manifest = {
requireCheckJarFile(jarFile.toURL)
new JarInputStream(new BufferedInputStream(new FileInputStream(jarFile))).getManifest
}
def copyProperties(original: Properties, target: Properties): Unit =
original.foreach(x => target.put(x._1, x._2))
def isLinux: Boolean = OS.indexOf("linux") >= 0
def isWindows: Boolean = OS.indexOf("windows") >= 0
/** if any blank strings exist */
def isAnyBank(items: String*): Boolean = items == null || items.exists(StringUtils.isBlank)
/**
* calculate the percentage of num1 / num2, the result range from 0 to 100, with one small digit
* reserve.
*/
def calPercent(num1: Long, num2: Long): Double =
if (num1 == 0 || num2 == 0) 0.0
else "%.1f".format(num1.toDouble / num2.toDouble * 100).toDouble
def hashCode(elements: Any*): Int = {
if (elements == null) return 0
var result = 1
for (elem <- elements) {
val hash = if (elem == null) 0 else elem.hashCode
result = 31 * result + hash
}
result
}
def close(closeable: AutoCloseable*)(implicit func: Throwable => Unit = null): Unit = {
closeable.foreach(
c => {
try {
if (c != null) {
c match {
case flushable: Flushable => flushable.flush()
case _ =>
}
c.close()
}
} catch {
case e: Throwable if func != null => func(e)
}
})
}
@tailrec
def retry[R](retryCount: Int, interval: Duration = Duration.ofSeconds(5))(f: => R): Try[R] = {
require(retryCount >= 0)
Try(f) match {
case Success(result) => Success(result)
case Failure(e) if retryCount > 0 =>
logWarn(s"Retry failed, execution caused by: ", e)
logWarn(
s"$retryCount times retry remaining, the next attempt will be in ${interval.toMillis} ms")
LockSupport.parkNanos(interval.toNanos)
retry(retryCount - 1, interval)(f)
case Failure(e) => Failure(e)
}
}
def checkHttpURL(urlString: String) = {
Try {
val url = new URL(urlString)
val connection = url.openConnection.asInstanceOf[HttpURLConnection]
connection.setRequestMethod("HEAD")
connection.getResponseCode == HttpURLConnection.HTTP_OK
}.getOrElse(false)
}
def printLogo(info: String): Unit = {
// scalastyle:off println
println("\n")
println(" _____ __ __ ")
println(" / ___// /_________ ____ _____ ___ ____ ____ ______/ /__ ")
println(" \\__ \\/ __/ ___/ _ \\/ __ `/ __ `__ \\/ __ \\ __ `/ ___/ //_/")
println(" ___/ / /_/ / / __/ /_/ / / / / / / /_/ / /_/ / / / ,< ")
println(" /____/\\__/_/ \\___/\\__,_/_/ /_/ /_/ ____/\\__,_/_/ /_/|_| ")
println(" /_/ \n\n")
println(" Version: 2.2.0-SNAPSHOT ")
println(" WebSite: https://streampark.apache.org ")
println(" GitHub : https://github.com/apache/incubator-streampark ")
println(s" Info : $info ")
println(s" Time : ${LocalDateTime.now} \n\n")
// scalastyle:on println
}
}