From d82b06ef8ed6976d3e2ca11c9923f154d91347c0 Mon Sep 17 00:00:00 2001 From: Sam Cao <sjtucaocao@gmail.com> Date: Wed, 2 Oct 2024 10:35:41 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B3=20chore:=20Add=20JavetBuddy=20v0.2?= =?UTF-8?q?.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + build.gradle.kts | 20 +- docs/release_notes.rst | 3 +- scripts/python/change_javet_version.py | 90 ------ scripts/python/requirements.txt | 1 - scripts/ts/change-version.ts | 107 ++++++ .../proxy/JavetReflectionObjectFactory.java | 305 ------------------ .../modules/javet/TestJavetModule.java | 2 +- .../javenode/modules/javet/TutorialJavet.java | 2 +- 9 files changed, 128 insertions(+), 407 deletions(-) delete mode 100644 scripts/python/change_javet_version.py delete mode 100644 scripts/python/requirements.txt create mode 100644 scripts/ts/change-version.ts delete mode 100644 src/main/java/com/caoccao/javet/interop/proxy/JavetReflectionObjectFactory.java diff --git a/.gitignore b/.gitignore index c6a0b6d..8c9d81c 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,8 @@ _build pom.xml.releaseBackup release.properties target + +# ------------------------------------------------------------------------------ +# Deno + +deno.lock diff --git a/build.gradle.kts b/build.gradle.kts index e835c3c..758144d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,13 +47,13 @@ object Config { } object Projects { - // https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy - const val BYTE_BUDDY = "net.bytebuddy:byte-buddy:${Versions.BYTE_BUDDY}" - const val JAVET = "com.caoccao.javet:javet:${Versions.JAVET}" const val JAVET_LINUX_ARM64 = "com.caoccao.javet:javet-linux-arm64:${Versions.JAVET}" const val JAVET_MACOS = "com.caoccao.javet:javet-macos:${Versions.JAVET}" + // https://mvnrepository.com/artifact/com.caoccao.javet.buddy/javet-buddy + const val JAVET_BUDDY = "com.caoccao.javet.buddy:javet-buddy:${Versions.JAVET_BUDDY}" + // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api const val JUNIT_JUPITER_API = "org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}" @@ -67,7 +67,8 @@ object Config { object Versions { const val BYTE_BUDDY = "1.14.10" const val JAVA_VERSION = "1.8" - const val JAVET = "3.1.7" + const val JAVET = "3.1.8" + const val JAVET_BUDDY = "0.2.0" const val JAVENODE = "0.8.0" const val JUNIT = "5.10.1" const val VERTX = "4.4.6" @@ -104,13 +105,16 @@ dependencies { val os = OperatingSystem.current() val cpuArch = System.getProperty("os.arch") if (os.isMacOsX) { - implementation(Config.Projects.JAVET_MACOS) + compileOnly(Config.Projects.JAVET_MACOS) + testImplementation(Config.Projects.JAVET_MACOS) } else if (os.isLinux && (cpuArch == "aarch64" || cpuArch == "arm64")) { - implementation(Config.Projects.JAVET_LINUX_ARM64) + compileOnly(Config.Projects.JAVET_LINUX_ARM64) + testImplementation(Config.Projects.JAVET_LINUX_ARM64) } else { - implementation(Config.Projects.JAVET) + compileOnly(Config.Projects.JAVET) + testImplementation(Config.Projects.JAVET) } - implementation(Config.Projects.BYTE_BUDDY) + implementation(Config.Projects.JAVET_BUDDY) implementation(Config.Projects.VERTX) testImplementation(Config.Projects.JUNIT_JUPITER_API) testRuntimeOnly(Config.Projects.JUNIT_JUPITER_ENGINE) diff --git a/docs/release_notes.rst b/docs/release_notes.rst index f312d08..836f336 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -5,7 +5,8 @@ Release Notes 0.8.0 ----- -* Upgraded Javet to v3.1.4 +* Upgraded Javet to v3.1.8 +* Added JavetBuddy v0.2.0 0.7.0 ----- diff --git a/scripts/python/change_javet_version.py b/scripts/python/change_javet_version.py deleted file mode 100644 index 8574869..0000000 --- a/scripts/python/change_javet_version.py +++ /dev/null @@ -1,90 +0,0 @@ -''' - Copyright (c) 2021-2024 caoccao.com Sam Cao - All rights reserved. - - 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. -''' - -import importlib -import logging -import pathlib -import re -import sys - -if importlib.util.find_spec('coloredlogs'): - import coloredlogs - coloredlogs.install(level=logging.DEBUG, fmt='%(asctime)-15s %(name)s %(levelname)s: %(message)s') - -class ChangeVersion(object): - - def __init__(self, version) -> None: - self._root_path = (pathlib.Path(__file__) / '../../../').resolve().absolute() - self._version = version - - def update_javenode(self): - self._update( - 'README.rst', '\n', - re.compile(r'^ <version>(?P<version>\d+\.\d+\.\d+)</version>$'), - re.compile(r'javenode[\-\w]*:(?P<version>\d+\.\d+\.\d+)["\']{1}')) - self._update( - 'build.gradle.kts', '\n', - re.compile(r'JAVENODE = "(?P<version>\d+\.\d+\.\d+)"$')) - self._update( - 'docs/conf.py', '\n', - re.compile(r'release\s*=\s*\'(?P<version>\d+\.\d+\.\d+)\'$')) - - def update_javet(self): - self._update( - 'build.gradle.kts', '\n', - re.compile(r'JAVET = "(?P<version>\d+\.\d+\.\d+)"$')) - - def _update(self, relative_file_path: str, line_separator: str, *patterns: list): - file_path = (self._root_path / relative_file_path).resolve().absolute() - logging.info('Updating %s.', str(file_path)) - lines, line_number = [], 1 - original_buffer = file_path.read_bytes() - for line in original_buffer.decode('utf-8').split(line_separator): - for pattern in patterns: - match_object = pattern.search(line) - if match_object is not None: - version = self._version - if ',' in match_object.group('version'): - version = version.replace('.', ',') - logging.info( - ' %d: %s -> %s', - line_number, - match_object.group('version'), - version) - line = '{prefix}{version}{suffix}'.format( - prefix=line[:match_object.start('version')], - version=version, - suffix=line[match_object.end('version'):]) - break - lines.append(line) - line_number += 1 - new_buffer = line_separator.join(lines).encode('utf-8') - if original_buffer == new_buffer: - logging.warning(' Skipped.') - else: - file_path.write_bytes(new_buffer) - logging.info(' Updated.') - -def main(): - change_javenode_version = ChangeVersion('0.8.0') - change_javenode_version.update_javenode() - change_javet_version = ChangeVersion('3.1.4') - change_javet_version.update_javet() - return 0 - -if __name__ == '__main__': - sys.exit(int(main() or 0)) diff --git a/scripts/python/requirements.txt b/scripts/python/requirements.txt deleted file mode 100644 index d895475..0000000 --- a/scripts/python/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -coloredlogs==14.0 diff --git a/scripts/ts/change-version.ts b/scripts/ts/change-version.ts new file mode 100644 index 0000000..4110c6e --- /dev/null +++ b/scripts/ts/change-version.ts @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2024. caoccao.com Sam Cao +* All rights reserved. + +* 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. +*/ + +import * as fs from "https://deno.land/std/fs/mod.ts"; +import * as path from "https://deno.land/std/path/mod.ts"; + +class ChangeVersion { + private productionVersion: string; + private rootDirPath: string; + private snapshotVersion: string; + + constructor(productionVersion: string, snapshotVersion: string) { + this.productionVersion = productionVersion; + this.snapshotVersion = snapshotVersion; + this.rootDirPath = path.join( + path.dirname(path.fromFileUrl(import.meta.url)), + "../../" + ); + } + + private _change( + filePath: string, + patterns: Array<RegExp>, + isSnapshot = true + ) { + const sourceFilePath = path.join(this.rootDirPath, filePath); + if (fs.existsSync(sourceFilePath)) { + console.info(`Processing ${sourceFilePath}.`); + } else { + console.error(`%c${sourceFilePath} is not found.`, "color: red"); + return; + } + const newVersion = isSnapshot + ? this.snapshotVersion + : this.productionVersion; + const positionGroups: Array<{ start: number; end: number }> = []; + const currentContent = Deno.readTextFileSync(sourceFilePath); + patterns.map((pattern) => { + [...currentContent.matchAll(pattern)].map((match) => { + const matchedString = match[0]; + if (match.groups) { + const currentVersion = match.groups["version"]; + if (newVersion === currentVersion) { + console.warn(`%c Ignored ${matchedString}`, "color: yellow"); + } else { + console.info(` ${matchedString} => ${newVersion}`); + const start = match.index + matchedString.indexOf(currentVersion); + const end = start + currentVersion.length; + positionGroups.push({ start: start, end: end }); + } + } + }); + }); + if (positionGroups.length > 0) { + let newContent = ""; + let lastEnd = 0; + positionGroups.sort((pg1, pg2) => pg1.start - pg2.start); + positionGroups.map((positionGroup) => { + if (positionGroup.start > lastEnd) { + newContent += currentContent.substring(lastEnd, positionGroup.start); + } + newContent += newVersion; + lastEnd = positionGroup.end; + }); + if (lastEnd < currentContent.length) { + newContent += currentContent.substring(lastEnd, currentContent.length); + } + if (newContent !== currentContent) { + Deno.writeTextFileSync(sourceFilePath, newContent); + } + } + } + + change() { + this._change( + "README.rst", + [ + /^\s*<version>(?<version>\d+\.\d+\.\d+)<\/version>/gim, + /javenode:(?<version>\d+\.\d+\.\d+)"/gim, + ], + false + ); + this._change("build.gradle.kts", [ + /^\s*const val JAVENODE = "(?<version>\d+\.\d+\.\d+)"/gim, + ]); + this._change("docs/conf.py", [ + /^release = "(?<version>\d+\.\d+\.\d+)"/gim, + ]); + } +} + +const changeVersion = new ChangeVersion("0.8.0", "0.8.0"); +changeVersion.change(); diff --git a/src/main/java/com/caoccao/javet/interop/proxy/JavetReflectionObjectFactory.java b/src/main/java/com/caoccao/javet/interop/proxy/JavetReflectionObjectFactory.java deleted file mode 100644 index a493134..0000000 --- a/src/main/java/com/caoccao/javet/interop/proxy/JavetReflectionObjectFactory.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2022. caoccao.com Sam Cao - * - * 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 com.caoccao.javet.interop.proxy; - -import com.caoccao.javet.interfaces.IJavetLogger; -import com.caoccao.javet.utils.JavetDefaultLogger; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.values.V8Value; -import com.caoccao.javet.values.reference.V8ValueFunction; -import com.caoccao.javet.values.reference.V8ValueObject; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.dynamic.DynamicType; -import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; -import net.bytebuddy.implementation.MethodDelegation; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; -import net.bytebuddy.implementation.bind.annotation.SuperCall; -import net.bytebuddy.matcher.ElementMatchers; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Locale; -import java.util.concurrent.Callable; - -/** - * The type Javet dynamic object factory. - * - * @since 2.0.1 - */ -public final class JavetReflectionObjectFactory implements IJavetReflectionObjectFactory { - private static final JavetReflectionObjectFactory instance = new JavetReflectionObjectFactory(); - private final IJavetLogger logger; - - private JavetReflectionObjectFactory() { - logger = new JavetDefaultLogger(getClass().getName()); - } - - /** - * Gets instance. - * - * @return the instance - * @since 2.0.1 - */ - public static JavetReflectionObjectFactory getInstance() { - return instance; - } - - @Override - public Object toObject(Class<?> type, V8Value v8Value) { - if (v8Value instanceof V8ValueObject) { - V8ValueObject v8ValueObject = null; - try { - DynamicObjectAutoCloseableInvocationHandler invocationHandler; - v8ValueObject = v8Value.toClone(); - if (AutoCloseable.class.isAssignableFrom(type)) { - invocationHandler = new DynamicObjectAutoCloseableInvocationHandler(type, v8ValueObject); - } else { - invocationHandler = new DynamicObjectForceCloseableInvocationHandler(type, v8ValueObject); - } - invocationHandler.initialize(); - return invocationHandler.getDynamicObject(); - } catch (Throwable t) { - logger.logError(t, "Failed to create dynamic object for {0}.", type.getName()); - JavetResourceUtils.safeClose(v8ValueObject); - } - } - return null; - } - - /** - * The type Dynamic object auto closeable invocation handler. - * - * @since 2.0.1 - */ - public static class DynamicObjectAutoCloseableInvocationHandler { - /** - * The constant CONSTRUCTOR_STRATEGY. - * - * @since 2.0.1 - */ - protected static final ConstructorStrategy CONSTRUCTOR_STRATEGY = - new ConstructorStrategy.ForDefaultConstructor(); - /** - * The constant METHOD_CLOSE. - * - * @since 2.0.1 - */ - protected static final String METHOD_CLOSE = "close"; - /** - * The Dynamic object. - * - * @since 2.0.1 - */ - protected Object dynamicObject; - /** - * The Type. - * - * @since 2.0.1 - */ - protected Class<?> type; - /** - * The V8 value object. - * - * @since 2.0.1 - */ - protected V8ValueObject v8ValueObject; - - /** - * Instantiates a new Dynamic object auto closeable invocation handler. - * - * @param type the type - * @param v8ValueObject the V8 value object - * @since 2.0.1 - */ - public DynamicObjectAutoCloseableInvocationHandler(Class<?> type, V8ValueObject v8ValueObject) { - this.type = type; - this.v8ValueObject = v8ValueObject; - } - - /** - * Close. - * - * @throws Exception the exception - * @since 2.0.1 - */ - public void close() throws Exception { - JavetResourceUtils.safeClose(v8ValueObject); - dynamicObject = null; - v8ValueObject = null; - } - - @Override - protected void finalize() throws Throwable { - close(); - } - - /** - * Gets dynamic object. - * - * @return the dynamic object - * @since 2.0.1 - */ - public Object getDynamicObject() { - return dynamicObject; - } - - /** - * Initialize. - * - * @throws IOException the io exception - * @throws NoSuchMethodException the no such method exception - * @throws InvocationTargetException the invocation target exception - * @throws InstantiationException the instantiation exception - * @throws IllegalAccessException the illegal access exception - * @since 2.0.1 - */ - public void initialize() - throws IOException, NoSuchMethodException, InvocationTargetException, - InstantiationException, IllegalAccessException { - Class<?> objectClass; - try (DynamicType.Unloaded<?> unloadedType = new ByteBuddy() - .subclass(type, CONSTRUCTOR_STRATEGY) - .method(ElementMatchers.isPublic()) - .intercept(MethodDelegation.to(this)) - .make()) { - objectClass = unloadedType.load(getClass().getClassLoader()).getLoaded(); - } - dynamicObject = objectClass.getConstructor().newInstance(); - } - - /** - * Intercept object. - * - * @param method the method - * @param arguments the arguments - * @param callable the callable - * @return the object - * @throws Exception the exception - * @since 2.0.1 - */ - @RuntimeType - public Object intercept( - @Origin Method method, - @AllArguments Object[] arguments, - @SuperCall Callable<Object> callable) throws Exception { - if (v8ValueObject != null) { - String methodName = method.getName(); - final int argumentLength = arguments.length; - if (METHOD_CLOSE.equals(methodName) && argumentLength == 0) { - close(); - return callable.call(); - } else if (v8ValueObject.has(methodName)) { - // Function or Property - try (V8Value v8ValueProperty = v8ValueObject.get(methodName)) { - if (v8ValueProperty instanceof V8ValueFunction) { - // Function - V8ValueFunction v8ValueFunction = (V8ValueFunction) v8ValueProperty; - return v8ValueFunction.callObject(null, arguments); - } else if (argumentLength == 0) { - // Property - return v8ValueObject.getV8Runtime().toObject(v8ValueProperty); - } - } - } else if (argumentLength == 0) { - // Getter - String propertyName = null; - if (methodName.startsWith(V8ValueObject.METHOD_PREFIX_IS)) { - propertyName = methodName.substring(V8ValueObject.METHOD_PREFIX_IS.length()); - } else if (methodName.startsWith(V8ValueObject.METHOD_PREFIX_GET)) { - propertyName = methodName.substring(V8ValueObject.METHOD_PREFIX_GET.length()); - } - if (propertyName != null && propertyName.length() > 0) { - propertyName = propertyName.substring(0, 1).toLowerCase(Locale.ROOT) - + propertyName.substring(1); - if (v8ValueObject.has(propertyName)) { - return v8ValueObject.getObject(propertyName); - } - } - } else if (argumentLength == 1) { - // Setter - String propertyName = null; - if (methodName.startsWith(V8ValueObject.METHOD_PREFIX_SET)) { - propertyName = methodName.substring(V8ValueObject.METHOD_PREFIX_SET.length()); - } - if (propertyName != null && propertyName.length() > 0) { - propertyName = propertyName.substring(0, 1).toLowerCase(Locale.ROOT) - + propertyName.substring(1); - if (v8ValueObject.has(propertyName)) { - return v8ValueObject.set(propertyName, arguments[0]); - } - } - } - } - return callable.call(); - } - } - - /** - * The type Dynamic object force closeable invocation handler. - * - * @since 2.0.1 - */ - public static class DynamicObjectForceCloseableInvocationHandler - extends DynamicObjectAutoCloseableInvocationHandler - implements AutoCloseable { - - /** - * Instantiates a new Dynamic object force closeable invocation handler. - * - * @param type the type - * @param v8ValueObject the V8 value object - * @since 2.0.1 - */ - public DynamicObjectForceCloseableInvocationHandler(Class<?> type, V8ValueObject v8ValueObject) { - super(type, v8ValueObject); - } - - @RuntimeType - @Override - public void close() throws Exception { - super.close(); - } - - @Override - public void initialize() - throws IOException, NoSuchMethodException, InvocationTargetException, - InstantiationException, IllegalAccessException { - Class<?> objectClass; - try (DynamicType.Unloaded<?> unloadedType = new ByteBuddy() - .subclass(type, CONSTRUCTOR_STRATEGY) - .implement(AutoCloseable.class) - .method(ElementMatchers.isPublic()) - .intercept(MethodDelegation.to(this)) - .make()) { - objectClass = unloadedType.load(getClass().getClassLoader()).getLoaded(); - } - dynamicObject = objectClass.getConstructor().newInstance(); - } - - @RuntimeType - @Override - public Object intercept( - @Origin Method method, - @AllArguments Object[] arguments, - @SuperCall Callable<Object> callable) throws Exception { - return super.intercept(method, arguments, callable); - } - } -} diff --git a/src/test/java/com/caoccao/javet/javenode/modules/javet/TestJavetModule.java b/src/test/java/com/caoccao/javet/javenode/modules/javet/TestJavetModule.java index bea20ab..c7efed6 100644 --- a/src/test/java/com/caoccao/javet/javenode/modules/javet/TestJavetModule.java +++ b/src/test/java/com/caoccao/javet/javenode/modules/javet/TestJavetModule.java @@ -17,10 +17,10 @@ package com.caoccao.javet.javenode.modules.javet; import com.caoccao.javet.annotations.V8Function; +import com.caoccao.javet.buddy.interop.proxy.JavetReflectionObjectFactory; import com.caoccao.javet.exceptions.JavetException; import com.caoccao.javet.interfaces.IJavetAnonymous; import com.caoccao.javet.interop.converters.JavetProxyConverter; -import com.caoccao.javet.interop.proxy.JavetReflectionObjectFactory; import com.caoccao.javet.javenode.BaseJNTestSuite; import com.caoccao.javet.javenode.enums.JNModuleType; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/caoccao/javet/javenode/modules/javet/TutorialJavet.java b/src/test/java/com/caoccao/javet/javenode/modules/javet/TutorialJavet.java index 9a0bd88..572e39e 100644 --- a/src/test/java/com/caoccao/javet/javenode/modules/javet/TutorialJavet.java +++ b/src/test/java/com/caoccao/javet/javenode/modules/javet/TutorialJavet.java @@ -16,11 +16,11 @@ package com.caoccao.javet.javenode.modules.javet; +import com.caoccao.javet.buddy.interop.proxy.JavetReflectionObjectFactory; import com.caoccao.javet.exceptions.JavetException; import com.caoccao.javet.interop.V8Host; import com.caoccao.javet.interop.V8Runtime; import com.caoccao.javet.interop.converters.JavetProxyConverter; -import com.caoccao.javet.interop.proxy.JavetReflectionObjectFactory; import com.caoccao.javet.javenode.JNEventLoop; import com.caoccao.javet.javenode.enums.JNModuleType;