├── .github
└── workflows
│ └── ci-workflow.yml
├── .gitignore
├── LICENSE
├── LICENSE-MIT
├── README.md
├── charity
├── README_CHARITY.md
└── smile_of_the_child_logo.png
├── java-fx
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── astonbitecode
│ │ │ └── j4rs
│ │ │ └── api
│ │ │ ├── invocation
│ │ │ ├── JavaFxInstanceGeneratorDelegate.java
│ │ │ └── JavaFxInvocation.java
│ │ │ └── jfx
│ │ │ ├── FxApplication.java
│ │ │ ├── FxApplicationStartCallback.java
│ │ │ ├── J4rsFxmlLoader.java
│ │ │ ├── controllers
│ │ │ ├── FxController.java
│ │ │ └── FxControllerImpl.java
│ │ │ ├── errors
│ │ │ ├── ComponentNotFoundException.java
│ │ │ └── FxException.java
│ │ │ └── handlers
│ │ │ └── J4rsEventHandler.java
│ └── resources
│ │ ├── MANIFEST.MF
│ │ └── META-INF
│ │ └── services
│ │ └── org.astonbitecode.j4rs.api.services.delegates.InstanceGeneratorDelegate
│ └── test
│ └── java
│ └── org
│ └── astonbitecode
│ └── j4rs
│ └── api
│ └── invocation
│ └── JavaFxInstanceGeneratorDelegateTest.java
├── java
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── astonbitecode
│ │ │ └── j4rs
│ │ │ ├── api
│ │ │ ├── Instance.java
│ │ │ ├── JsonValue.java
│ │ │ ├── NativeInstantiation.java
│ │ │ ├── ObjectValue.java
│ │ │ ├── async
│ │ │ │ ├── J4rsAsyncContext.java
│ │ │ │ └── J4rsPolledFuture.java
│ │ │ ├── deploy
│ │ │ │ ├── DeployUtils.java
│ │ │ │ ├── FileSystemDeployer.java
│ │ │ │ ├── J4rsClassLoader.java
│ │ │ │ └── SimpleMavenDeployer.java
│ │ │ ├── dtos
│ │ │ │ ├── GeneratedArg.java
│ │ │ │ ├── InvocationArg.java
│ │ │ │ └── InvocationArgGenerator.java
│ │ │ ├── instantiation
│ │ │ │ └── NativeInstantiationImpl.java
│ │ │ ├── invocation
│ │ │ │ ├── InstanceGenerator.java
│ │ │ │ ├── JsonInvocationImpl.java
│ │ │ │ ├── NativeCallbackToRustChannelSupport.java
│ │ │ │ └── NativeCallbackToRustFutureSupport.java
│ │ │ ├── java2rust
│ │ │ │ └── Java2RustUtils.java
│ │ │ ├── services
│ │ │ │ ├── delegates
│ │ │ │ │ └── InstanceGeneratorDelegate.java
│ │ │ │ └── json
│ │ │ │ │ ├── Codec.java
│ │ │ │ │ └── exceptions
│ │ │ │ │ └── JsonCodecException.java
│ │ │ └── value
│ │ │ │ ├── JsonValueFactory.java
│ │ │ │ ├── JsonValueImpl.java
│ │ │ │ ├── NullJsonValueImpl.java
│ │ │ │ └── NullObject.java
│ │ │ ├── errors
│ │ │ ├── InstantiationException.java
│ │ │ ├── InvalidArgumentException.java
│ │ │ └── InvocationException.java
│ │ │ ├── json
│ │ │ ├── JacksonCodec.java
│ │ │ └── JsonCodecService.java
│ │ │ ├── rust
│ │ │ ├── FunctionPointer.java
│ │ │ └── RustPointer.java
│ │ │ └── utils
│ │ │ └── Utils.java
│ └── resources
│ │ └── MANIFEST.MF
│ └── test
│ └── java
│ └── org
│ └── astonbitecode
│ └── j4rs
│ ├── api
│ ├── deploy
│ │ ├── FileSystemDeployerTest.java
│ │ └── SimpleMavenDeployerTest.java
│ ├── dtos
│ │ └── InvocationArgTest.java
│ ├── instantiation
│ │ └── NativeInstantiationImplTest.java
│ └── invocation
│ │ ├── InstanceGeneratorTest.java
│ │ ├── JsonInvocationImplTest.java
│ │ └── NativeCallbackToRustChannelSupportTest.java
│ ├── json
│ └── JacksonCodecTest.java
│ ├── tests
│ └── MyTestTest.java
│ ├── utils
│ ├── ChildDummy.java
│ ├── ChildOfDummyWithFields.java
│ ├── ClassWithDummyAtConstructor.java
│ ├── Dummy.java
│ ├── DummyInterface.java
│ ├── DummyInterfaceFather.java
│ ├── DummyInterfaceMother.java
│ ├── DummyMapImpl.java
│ ├── DummyMapInterface.java
│ ├── DummyWithFields.java
│ ├── DummyWithStatic.java
│ ├── FailingDummy.java
│ ├── GrandchildDummy.java
│ └── OtherDummy.java
│ └── value
│ └── JsonValueImplTest.java
├── rust
├── .gitignore
├── Cargo.toml
├── Cross.toml
├── README.md
├── benches
│ └── j4rs_benchmark.rs
├── build.rs
├── j4rs_derive
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
├── jassets
│ └── j4rs-0.23.0-SNAPSHOT-jar-with-dependencies.jar
└── src
│ ├── api
│ ├── instance.rs
│ ├── invocation_arg.rs
│ └── mod.rs
│ ├── api_tweaks
│ ├── android.rs
│ ├── generic.rs
│ ├── mod.rs
│ └── no_runtime_lib_loading.rs
│ ├── async_api
│ └── mod.rs
│ ├── cache.rs
│ ├── errors.rs
│ ├── jfx.rs
│ ├── jni_utils.rs
│ ├── lib.rs
│ ├── logger.rs
│ ├── prelude.rs
│ ├── provisioning.rs
│ └── utils.rs
├── static
└── j4rs-small.png
└── test-resources
└── java
├── pom.xml
└── src
└── main
├── java
└── org
│ └── astonbitecode
│ └── j4rs
│ └── tests
│ ├── DummyMapImpl.java
│ ├── DummyMapInterface.java
│ ├── MyBean.java
│ ├── MySecondTest.java
│ └── MyTest.java
└── resources
└── MANIFEST.MF
/.github/workflows/ci-workflow.yml:
--------------------------------------------------------------------------------
1 | name: j4rs CI
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | build:
14 | runs-on: ${{ matrix.os }}
15 |
16 | strategy:
17 | matrix:
18 | os: [ ubuntu-latest, macos-latest, windows-latest ]
19 |
20 | steps:
21 | - uses: actions/checkout@v3
22 | - name: Set up JDK 17
23 | uses: actions/setup-java@v3
24 | with:
25 | java-version: '17'
26 | distribution: 'adopt'
27 | - name: Build and Test Java with Maven
28 | run: mvn -f ./java/pom.xml --batch-mode --update-snapshots install
29 | - name: Build and Test the JavaFX module with Maven
30 | run: mvn -f ./java/pom.xml --batch-mode --update-snapshots install
31 | - name: Build and install Java testing resources with Maven
32 | run: mvn -f ./test-resources/java/pom.xml --batch-mode --update-snapshots install
33 | - name: Build Rust with Cargo
34 | run: cargo build --manifest-path ./rust/Cargo.toml --verbose
35 | - name: Test Rust with Cargo
36 | run: cargo test --manifest-path ./rust/Cargo.toml --verbose
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.project
2 | **/target/
3 | **/*.rs.bk
4 | **/.idea/
5 | **/*.iml
6 | **/Cargo.lock
7 | **/settings/
8 | **/primer/
9 | **/.settings
10 | **/.classpath
11 | *.code-workspace
12 | **/.vscode/
13 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 astonbitecode
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/charity/README_CHARITY.md:
--------------------------------------------------------------------------------
1 | # The Smile of the Child
2 |
3 | [](https://www.hamogelo.gr/gr/en/poioi-eimaste/)
4 |
5 | "[The Smile of the Child](https://www.hamogelo.gr/gr/en/poioi-eimaste/)" was created in 1995 by 10-year-old Andreas Yannopoulos, who, shortly before leaving from life, expressed in his diary his wish to found an organization that will ensure for all children what he had so generously enjoyed: love, affection, care and respect.
6 |
7 | The financial data of the Organization is publicized on an annual basis and is audited by International Body of Auditors of Ernst and Young.
8 |
9 | ---
10 |
11 | ### Please consider donating; there are [many ways](https://www.hamogelo.gr/gr/en/stirikste-mas/) to do so.
12 |
13 | _Note: `j4rs` is not affiliated with "The Smile of the Child", we just want to help and contribute to the longevity of the organization._
--------------------------------------------------------------------------------
/charity/smile_of_the_child_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/astonbitecode/j4rs/40614a8dbe9a32ca51c5cc63c3ec3b3ebd75b766/charity/smile_of_the_child_logo.png
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/invocation/JavaFxInstanceGeneratorDelegate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.api.services.delegates.InstanceGeneratorDelegate;
19 |
20 | public class JavaFxInstanceGeneratorDelegate implements InstanceGeneratorDelegate {
21 | @Override
22 | public Instance proxy(Instance instance) {
23 | return new JavaFxInvocation(instance);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/invocation/JavaFxInvocation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import javafx.application.Platform;
18 | import org.astonbitecode.j4rs.api.Instance;
19 | import org.astonbitecode.j4rs.api.dtos.InvocationArg;
20 | import org.astonbitecode.j4rs.errors.InvocationException;
21 |
22 | import java.util.concurrent.CompletableFuture;
23 | import java.util.concurrent.ExecutionException;
24 |
25 | public class JavaFxInvocation implements Instance {
26 | private Instance jsonInvocation;
27 |
28 | public JavaFxInvocation(Instance jsonInvocation) {
29 | this.jsonInvocation = jsonInvocation;
30 | }
31 |
32 | @Override
33 | public Instance invoke(String methodName, InvocationArg... args) {
34 | CompletableFuture> f = new CompletableFuture();
35 | Platform.runLater(() -> {
36 | Instance i = jsonInvocation.invoke(methodName, args);
37 | f.complete(i);
38 | });
39 |
40 | try {
41 | return f.get();
42 | } catch (InterruptedException | ExecutionException error) {
43 | throw new InvocationException("While invoking method " + methodName + " of Class "
44 | + this.jsonInvocation.getObjectClass().getName(), error);
45 | }
46 | }
47 |
48 | @Override
49 | public Instance invokeStatic(String methodName, InvocationArg... args) {
50 | CompletableFuture> f = new CompletableFuture();
51 | Platform.runLater(() -> {
52 | Instance i = jsonInvocation.invokeStatic(methodName, args);
53 | f.complete(i);
54 | });
55 |
56 | try {
57 | return f.get();
58 | } catch (InterruptedException | ExecutionException error) {
59 | throw new InvocationException("While invoking method " + methodName + " of Class "
60 | + this.jsonInvocation.getObjectClass().getName(), error);
61 | }
62 | }
63 |
64 | @Override
65 | public void invokeAsyncToChannel(long channelAddress, String methodName, InvocationArg... args) {
66 | Platform.runLater(() -> jsonInvocation.invokeAsyncToChannel(channelAddress, methodName, args));
67 | }
68 |
69 | @Override
70 | public void invokeToChannel(long channelAddress, String methodName, InvocationArg... args) {
71 | System.out.println("Invoking to channel " + methodName + " with " + args.length + " args");
72 | Platform.runLater(() -> {
73 | jsonInvocation.invokeToChannel(channelAddress, methodName, args);
74 | });
75 | }
76 |
77 | @Override
78 | public void initializeCallbackChannel(long channelAddress) {
79 | jsonInvocation.initializeCallbackChannel(channelAddress);
80 | }
81 |
82 | @Override
83 | public Instance> field(String fieldName) {
84 | return jsonInvocation.field(fieldName);
85 | }
86 |
87 | @Override
88 | public String getJson() {
89 | return jsonInvocation.getJson();
90 | }
91 |
92 | @Override
93 | public Object getObject() {
94 | return jsonInvocation.getObject();
95 | }
96 |
97 | @Override
98 | public Class> getObjectClass() {
99 | return jsonInvocation.getObjectClass();
100 | }
101 |
102 | @Override
103 | public String getObjectClassName() {
104 | return jsonInvocation.getObjectClassName();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/FxApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx;
16 |
17 | import javafx.application.Application;
18 | import javafx.stage.Stage;
19 | import org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport;
20 |
21 | import java.util.concurrent.atomic.AtomicReference;
22 |
23 | /**
24 | * Manipulates a JavaFX application
25 | */
26 | public class FxApplication extends Application {
27 | private static final AtomicReference callback = new AtomicReference<>(null);
28 |
29 | @Override
30 | public void start(Stage fxStage) {
31 | callback.get().doCallback(fxStage);
32 | }
33 |
34 | /**
35 | * Sets a channel callback for j4rs
36 | * @param nativeCallbackToRustChannelSupport A {@link NativeCallbackToRustChannelSupport}
37 | */
38 | static void setCallback(NativeCallbackToRustChannelSupport nativeCallbackToRustChannelSupport) {
39 | callback.getAndSet(nativeCallbackToRustChannelSupport);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/FxApplicationStartCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx;
16 |
17 | import javafx.application.Application;
18 | import org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport;
19 |
20 | public class FxApplicationStartCallback extends NativeCallbackToRustChannelSupport {
21 | public void setCallbackToApplicationAndLaunch() {
22 | FxApplication.setCallback(this);
23 | new Thread(() -> Application.launch(FxApplication.class)).start();
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/J4rsFxmlLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx;
16 |
17 | import javafx.fxml.FXMLLoader;
18 | import javafx.scene.Parent;
19 | import javafx.scene.Scene;
20 | import javafx.stage.Stage;
21 | import org.astonbitecode.j4rs.api.jfx.controllers.FxController;
22 | import org.astonbitecode.j4rs.api.jfx.controllers.FxControllerImpl;
23 | import org.astonbitecode.j4rs.api.jfx.errors.FxException;
24 |
25 | import java.io.File;
26 | import java.io.IOException;
27 | import java.net.URL;
28 |
29 | @SuppressWarnings("unused")
30 | public class J4rsFxmlLoader {
31 | /**
32 | * Loads a FXML and returns an {@link FxController} for it.
33 | *
34 | * @param stage The {@link Stage} to load the FXML on.
35 | * @param fxmlPath The location of the FXML file.
36 | * @return A {@link FxController} instance.
37 | * @throws IOException In case that the FXML cannot be loaded.
38 | * @throws FxException In case the fxml cannot be loaded
39 | */
40 | @SuppressWarnings("unused")
41 | public static FxController loadFxml(Stage stage, String fxmlPath) throws IOException, FxException {
42 | FXMLLoader loader = new FXMLLoader();
43 | URL resurl = new File(fxmlPath).toURI().toURL();
44 | loader.setControllerFactory(clazz -> new FxControllerImpl());
45 | loader.setLocation(resurl);
46 | Parent root = loader.load();
47 |
48 | Scene scene = new Scene(root);
49 | stage.setScene(scene);
50 |
51 | FxController controller = loader.getController();
52 | if (controller == null) {
53 | throw new FxException(String.format(
54 | "Could not load the fxml %s. Please make sure that its root element contains fx:controller=\"org.astonbitecode.j4rs.api.jfx.controllers.FxController\"",
55 | fxmlPath));
56 | }
57 | controller.setScene(scene);
58 |
59 | return controller;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/controllers/FxController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx.controllers;
16 |
17 | import javafx.event.Event;
18 | import javafx.event.EventHandler;
19 | import javafx.event.EventType;
20 | import javafx.fxml.Initializable;
21 | import javafx.scene.Node;
22 | import javafx.scene.Scene;
23 | import org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport;
24 | import org.astonbitecode.j4rs.api.jfx.errors.ComponentNotFoundException;
25 |
26 | public interface FxController extends Initializable {
27 | /**
28 | * This will be called when the initialize method of {@link Initializable} is
29 | * called.
30 | *
31 | * @param callback The callback to add.
32 | */
33 | @SuppressWarnings("unused")
34 | void addControllerInitializedCallback(NativeCallbackToRustChannelSupport callback);
35 |
36 | /**
37 | * Add a handler for an {@link javafx.event.ActionEvent} that comes from a
38 | * component with a specific id.
39 | *
40 | * @param id The id of the callback.
41 | * @param handler The handler to add.
42 | * @param eventType The EventType for Event to handle.
43 | * @throws ComponentNotFoundException in case the handler is not found
44 | */
45 | @SuppressWarnings("unused")
46 | void addEventHandler(String id, EventHandler handler, EventType> eventType)
47 | throws ComponentNotFoundException;
48 |
49 | /**
50 | * Retrieves a node given its ID.
51 | *
52 | * @param id The id of the node to retrieve.
53 | * @return The {@link Node} found.
54 | * @throws ComponentNotFoundException In case that the node is not found.
55 | */
56 | Node getNodeById(String id) throws ComponentNotFoundException;
57 |
58 | /**
59 | * Sets a scene for this controller.
60 | *
61 | * @param scene The scene to set.
62 | */
63 | void setScene(Scene scene);
64 | }
65 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/controllers/FxControllerImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx.controllers;
16 |
17 | import javafx.event.Event;
18 | import javafx.event.EventHandler;
19 | import javafx.event.EventType;
20 | import javafx.scene.Node;
21 | import javafx.scene.Scene;
22 | import org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport;
23 | import org.astonbitecode.j4rs.api.jfx.errors.ComponentNotFoundException;
24 |
25 | import java.net.URL;
26 | import java.util.ResourceBundle;
27 | import java.util.concurrent.atomic.AtomicBoolean;
28 | import java.util.concurrent.atomic.AtomicReference;
29 |
30 | public class FxControllerImpl implements FxController {
31 | private Scene scene;
32 | private AtomicReference initializeCb = new AtomicReference<>(null);
33 | private AtomicBoolean controllerLoaded = new AtomicBoolean(false);
34 |
35 | @Override
36 | public void initialize(URL url, ResourceBundle resourceBundle) {
37 | controllerLoaded.getAndSet(true);
38 | if (initializeCb.get() != null) {
39 | initializeCb.get().doCallback(new Object());
40 | }
41 | }
42 |
43 | @Override
44 | public void addControllerInitializedCallback(NativeCallbackToRustChannelSupport callback) {
45 | initializeCb.getAndSet(callback);
46 | if (controllerLoaded.get()) {
47 | callback.doCallback(new Object());
48 | }
49 | }
50 |
51 | @Override
52 | public void addEventHandler(String id, EventHandler handler, EventType> eventType)
53 | throws ComponentNotFoundException {
54 | Node node = getNodeById(id);
55 | node.addEventHandler(eventType, handler);
56 | }
57 |
58 | @Override
59 | public Node getNodeById(String id) throws ComponentNotFoundException {
60 | if (scene != null) {
61 | Node node = scene.lookup("#" + id);
62 | if (node != null) {
63 | return node;
64 | }
65 | }
66 | throw new ComponentNotFoundException(String.format("Node with id %s was not found.", id));
67 | }
68 |
69 | @Override
70 | public void setScene(Scene scene) {
71 | this.scene = scene;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/errors/ComponentNotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx.errors;
16 |
17 | /**
18 | * Exception thrown if a JavaFX component is not found
19 | */
20 | public class ComponentNotFoundException extends Exception {
21 | /**
22 | * Instantiate with a message
23 | * @param message A message
24 | */
25 | public ComponentNotFoundException(String message) {
26 | super(message);
27 | }
28 |
29 | /**
30 | * Instantiate with a {@link Throwable}
31 | * @param throwable The Throwable
32 | */
33 | @SuppressWarnings("unused")
34 | public ComponentNotFoundException(Throwable throwable) {
35 | super(throwable);
36 | }
37 |
38 | /**
39 | * Instantiate with a message and a {@link Throwable}
40 | * @param message The message
41 | * @param throwable The throwable
42 | */
43 | @SuppressWarnings("unused")
44 | public ComponentNotFoundException(String message, Throwable throwable) {
45 | super(message, throwable);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/errors/FxException.java:
--------------------------------------------------------------------------------
1 | package org.astonbitecode.j4rs.api.jfx.errors;
2 |
3 | public class FxException extends Exception {
4 | public FxException(String message) {
5 | super(message);
6 | }
7 |
8 | public FxException(Throwable throwable) {
9 | super(throwable);
10 | }
11 |
12 | public FxException(String message, Throwable throwable) {
13 | super(message, throwable);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/java-fx/src/main/java/org/astonbitecode/j4rs/api/jfx/handlers/J4rsEventHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.jfx.handlers;
16 |
17 | import javafx.event.Event;
18 | import javafx.event.EventHandler;
19 | import org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport;
20 |
21 | public class J4rsEventHandler extends NativeCallbackToRustChannelSupport implements EventHandler {
22 | @Override
23 | public void handle(T event) {
24 | doCallback(event);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/java-fx/src/main/resources/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Built-By: astonbitecode
2 | url: https://github.com/astonbitecode/j4rs
3 |
--------------------------------------------------------------------------------
/java-fx/src/main/resources/META-INF/services/org.astonbitecode.j4rs.api.services.delegates.InstanceGeneratorDelegate:
--------------------------------------------------------------------------------
1 | org.astonbitecode.j4rs.api.invocation.JavaFxInstanceGeneratorDelegate
--------------------------------------------------------------------------------
/java-fx/src/test/java/org/astonbitecode/j4rs/api/invocation/JavaFxInstanceGeneratorDelegateTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.junit.Ignore;
19 |
20 | import javafx.scene.layout.StackPane;
21 |
22 | public class JavaFxInstanceGeneratorDelegateTest {
23 | @Ignore
24 | public void generateCorrectImpl() {
25 | Instance> javaFxInstance = InstanceGenerator.create(new StackPane(), StackPane.class);
26 | assert (javaFxInstance.getClass().equals(JavaFxInvocation.class));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/Instance.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api;
16 |
17 | import org.astonbitecode.j4rs.api.dtos.InvocationArg;
18 | import org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl;
19 | import org.astonbitecode.j4rs.api.value.JsonValueFactory;
20 | import org.astonbitecode.j4rs.errors.InvocationException;
21 | import org.astonbitecode.j4rs.utils.Utils;
22 |
23 | public interface Instance extends ObjectValue, JsonValue {
24 | /**
25 | * Invokes a method of the instance of the class that is set for this
26 | * {@link Instance}
27 | *
28 | * @param methodName The method name
29 | * @param args The arguments to use for invoking the method
30 | * @return A {@link Instance} instance containing the result of the invocation
31 | */
32 | Instance invoke(String methodName, InvocationArg... args);
33 |
34 | /**
35 | * Invokes a static method of the class that is set for this {@link Instance}
36 | *
37 | * @param methodName The static method name
38 | * @param args The arguments to use for invoking the static method
39 | * @return A {@link Instance} instance containing the result of the invocation
40 | */
41 | Instance invokeStatic(String methodName, InvocationArg... args);
42 |
43 | /**
44 | * Invokes asynchronously a method of the instance of the class that is set for
45 | * this {@link Instance}. The result of the invocation must be a
46 | * {@link java.util.concurrent.Future}. When the Future returned from the
47 | * invocation completes, j4rs will invoke native Rust code to either send a
48 | * success value or a failure.
49 | *
50 | * Please note that it is best that this function returns a
51 | * {@link java.util.concurrent.CompletableFuture}, as this improves performance.
52 | * j4rs handles simple {@link java.util.concurrent.Future}s with polling using
53 | * an internal {@link java.util.concurrent.ScheduledExecutorService} with one
54 | * thread and this has apparent performance issues. You may have a look at
55 | * {@link org.astonbitecode.j4rs.api.async.J4rsPolledFuture} for more details.
56 | *
57 | * @param functionPointerAddress The address of the function pointer that will
58 | * be used when the
59 | * {@link java.util.concurrent.Future} completes,
60 | * in the native side, in order to actually
61 | * perform the callback and complete a Future that
62 | * is created in Rust and awaits for the Java
63 | * Future to complete.
64 | * @param methodName The method name
65 | * @param args The arguments to use when invoking the callback
66 | * method (the functionPointer)
67 | */
68 | void invokeAsyncToChannel(long functionPointerAddress, String methodName, InvocationArg... args);
69 |
70 | /**
71 | * Invokes a method of the instance of the class that is set for this
72 | * {@link Instance}. The result of the invocation should be provided later using
73 | * the doCallback method of a
74 | * {@link org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport}
75 | * class. Any possible returned objects from the actual synchronous invocation
76 | * of the defined method will be dropped.
77 | *
78 | * @param channelAddress The memory address of the channel
79 | * @param methodName The method name
80 | * @param args The arguments
81 | */
82 | void invokeToChannel(long channelAddress, String methodName, InvocationArg... args);
83 |
84 | /**
85 | * Initialize a callback channel for this {@link Instance}. The channel can be
86 | * used by Java to send values to Rust using the doCallback method of a
87 | * {@link org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport}
88 | * class.
89 | *
90 | * @param channelAddress The memory address of the channel
91 | */
92 | void initializeCallbackChannel(long channelAddress);
93 |
94 | /**
95 | * Retrieves the instance held under the Field fieldName
96 | *
97 | * @param fieldName The name of the field to retrieve
98 | * @return A {@link Instance} instance containing the defined field.
99 | */
100 | Instance field(String fieldName);
101 |
102 | /**
103 | * Casts a the object that is contained in a Instance to an object of class
104 | * clazz.
105 | *
106 | * @param Generically defined return type
107 | * @param from The {@link Instance} to cast.
108 | * @param toClass The class that the provided {@link Instance} should be casted
109 | * to
110 | * @return A {@link Instance} instance containing the result of the cast.
111 | */
112 | static Instance cast(Instance from, String toClass) {
113 | try {
114 | Class clazz = (Class) Utils.forNameEnhanced(toClass);
115 | return new JsonInvocationImpl(clazz.cast(from.getObject()), clazz);
116 | } catch (Exception error) {
117 | throw new InvocationException(
118 | "Cannot cast instance of " + from.getObject().getClass().getName() + " to " + toClass, error);
119 | }
120 | }
121 |
122 | /**
123 | * Clones a Instance
124 | *
125 | * @param from The object to clone.
126 | * @param Generically defined return type
127 | * @return a {@link Instance} instance.
128 | */
129 | static Instance cloneInstance(Instance from) {
130 | return new JsonInvocationImpl(from.getObject(), from.getObjectClass());
131 | }
132 |
133 | default T getOrDeserializeJavaObject() {
134 | boolean isSerialized = false;
135 | if (InvocationArg.class.isAssignableFrom(this.getClass())) {
136 | isSerialized = ((InvocationArg) this).isSerialized();
137 | }
138 | if (!isSerialized) {
139 | return (T) this.getObject();
140 | } else {
141 | ObjectValue objValue = JsonValueFactory.create(this.getJson(), this.getObjectClassName());
142 | return (T) objValue.getObject();
143 | }
144 | }
145 |
146 | default boolean checkEquals(Instance other) {
147 | T a = this.getOrDeserializeJavaObject();
148 | U b = other.getOrDeserializeJavaObject();
149 | if (a != null && b != null) {
150 | return a.equals(b);
151 | } else if (a == null && b == null) {
152 | return true;
153 | } else {
154 | return false;
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/JsonValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api;
16 |
17 | /**
18 | * Representation for a json value
19 | */
20 | public interface JsonValue extends ObjectValue {
21 | /**
22 | * Returns the json representation
23 | * @return The json representation
24 | */
25 | String getJson();
26 | }
27 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/NativeInstantiation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api;
16 |
17 | import org.astonbitecode.j4rs.api.dtos.InvocationArg;
18 |
19 | public interface NativeInstantiation {
20 | Instance instantiate(String className, InvocationArg... arg);
21 |
22 | Instance createForStatic(String className);
23 |
24 | Instance createJavaArray(String className, InvocationArg... arg);
25 | }
26 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/ObjectValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api;
16 |
17 | /**
18 | * Represents an object for j4rs needs
19 | */
20 | public interface ObjectValue {
21 | /**
22 | * Returns the Object
23 | * @return An object instance
24 | */
25 | Object getObject();
26 |
27 | /**
28 | * Returns the {@link Class} of the Object
29 | * @return A {@link Class}
30 | */
31 | Class> getObjectClass();
32 |
33 | /**
34 | * Returns the name of the Object Class
35 | * @return A String representing the name of the Object Class
36 | */
37 | String getObjectClassName();
38 | }
39 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/async/J4rsAsyncContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.async;
16 |
17 | import java.util.concurrent.Executors;
18 | import java.util.concurrent.ScheduledExecutorService;
19 | import java.util.concurrent.TimeUnit;
20 |
21 | class J4rsAsyncContext {
22 | private static final ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor();
23 |
24 | static void schedule(Runnable r) {
25 | SERVICE.schedule(r, 10, TimeUnit.NANOSECONDS);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/async/J4rsPolledFuture.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.async;
16 |
17 | import java.util.concurrent.CompletableFuture;
18 | import java.util.concurrent.ExecutionException;
19 | import java.util.concurrent.Future;
20 |
21 | /**
22 | * A {@link CompletableFuture} that completes by polling a {@link Future}.
23 | *
24 | * @param A type
25 | */
26 | public class J4rsPolledFuture extends CompletableFuture {
27 | private final Future future;
28 |
29 | public J4rsPolledFuture(Future future) {
30 | this.future = future;
31 | J4rsAsyncContext.schedule(this::tryToComplete);
32 | }
33 |
34 | private void tryToComplete() {
35 | if (future.isDone()) {
36 | try {
37 | complete(future.get());
38 | } catch (InterruptedException error) {
39 | completeExceptionally(error);
40 | } catch (ExecutionException error) {
41 | completeExceptionally(error.getCause());
42 | }
43 | return;
44 | }
45 |
46 | if (future.isCancelled()) {
47 | cancel(true);
48 | return;
49 | }
50 |
51 | J4rsAsyncContext.schedule(this::tryToComplete);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/deploy/DeployUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.deploy;
16 |
17 | import java.io.File;
18 | import java.net.MalformedURLException;
19 |
20 | public class DeployUtils {
21 | /**
22 | * Adds a jar to the classpath
23 | * @param fullJarPath The full path of the jar to add
24 | * @throws MalformedURLException In case the path is not valid
25 | */
26 | static void addToClasspath(String fullJarPath) throws MalformedURLException {
27 | if (ClassLoader.getSystemClassLoader().getClass().isAssignableFrom(J4rsClassLoader.class)) {
28 | J4rsClassLoader classLoader = (J4rsClassLoader) ClassLoader.getSystemClassLoader();
29 | File jar = new File(fullJarPath);
30 | classLoader.add(jar.toURI().toURL());
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/deploy/FileSystemDeployer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.deploy;
16 |
17 | import java.io.File;
18 | import java.io.FileOutputStream;
19 | import java.io.IOException;
20 | import java.nio.channels.Channels;
21 | import java.nio.channels.ReadableByteChannel;
22 |
23 | /**
24 | * Deploys a resource to be used by j4rs.
25 | */
26 | public class FileSystemDeployer {
27 | private final String deployTarget;
28 |
29 | /**
30 | * Generates a default {@link FileSystemDeployer} with target the working directory
31 | */
32 | public FileSystemDeployer() {
33 | this(".");
34 | }
35 |
36 | /**
37 | * Generates a {@link FileSystemDeployer} defining the deploy target
38 | * @param deployTarget The target path for the deployments
39 | */
40 | public FileSystemDeployer(String deployTarget) {
41 | this.deployTarget = deployTarget;
42 | new File(deployTarget).mkdirs();
43 | }
44 |
45 | /**
46 | * Deploys a resource. The resource may be automatically added to the classpath for j4rs
47 | * @param path The path of the resource
48 | * @throws IOException In case the path is invalid or the resource cannot be accessed
49 | */
50 | public void deploy(String path) throws IOException {
51 | File jarFile = new File(path);
52 | ReadableByteChannel readableByteChannel = Channels.newChannel(jarFile.toURI().toURL().openStream());
53 | String fullJarDeployPath = deployTarget + File.separator + jarFile.getName();
54 | try (FileOutputStream fileOutputStream = new FileOutputStream(fullJarDeployPath)) {
55 | fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
56 | }
57 | DeployUtils.addToClasspath(fullJarDeployPath);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/deploy/J4rsClassLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.deploy;
16 |
17 | import java.net.URL;
18 | import java.net.URLClassLoader;
19 |
20 | public final class J4rsClassLoader extends URLClassLoader {
21 | public J4rsClassLoader(ClassLoader offeredClassLoader) {
22 | super("j4rsClassLoader", new URL[0], offeredClassLoader);
23 | }
24 |
25 | void add(URL url) {
26 | addURL(url);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/deploy/SimpleMavenDeployer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.deploy;
16 |
17 | import org.w3c.dom.Document;
18 | import org.w3c.dom.Node;
19 | import org.w3c.dom.NodeList;
20 | import org.xml.sax.SAXException;
21 |
22 | import javax.xml.parsers.DocumentBuilder;
23 | import javax.xml.parsers.DocumentBuilderFactory;
24 | import javax.xml.parsers.ParserConfigurationException;
25 | import javax.xml.xpath.XPath;
26 | import javax.xml.xpath.XPathConstants;
27 | import javax.xml.xpath.XPathExpressionException;
28 | import javax.xml.xpath.XPathFactory;
29 | import java.io.*;
30 | import java.net.MalformedURLException;
31 | import java.net.URL;
32 | import java.nio.channels.Channels;
33 | import java.nio.channels.ReadableByteChannel;
34 |
35 | public class SimpleMavenDeployer {
36 | private static final String MAVEN_CENTRAL = "https://repo.maven.apache.org/maven2";
37 | private final String M2_CACHE = System.getProperty("user.home") + File.separator + ".m2" + File.separator
38 | + "repository";
39 |
40 | private final String repoBase;
41 | private final boolean checkLocalCache;
42 | private final String deployTarget;
43 |
44 | public SimpleMavenDeployer() {
45 | this(MAVEN_CENTRAL, true, ".");
46 | }
47 |
48 | public SimpleMavenDeployer(String deployTarget) {
49 | this(MAVEN_CENTRAL, true, deployTarget);
50 | }
51 |
52 | public SimpleMavenDeployer(String repoBase, String deployTarget) {
53 | this(repoBase, true, deployTarget);
54 | }
55 |
56 | public SimpleMavenDeployer(String repoBase, boolean checkLocalCache, String deployTarget) {
57 | this.repoBase = repoBase;
58 | this.checkLocalCache = checkLocalCache;
59 | this.deployTarget = deployTarget;
60 | new File(deployTarget).mkdirs();
61 | }
62 |
63 | public void deploy(String groupId, String artifactId, String version, String qualifier) throws IOException {
64 | String jarName = generateArtifactName(artifactId, version, qualifier);
65 | boolean searchRemoteRepo = true;
66 |
67 | if (!artifactExists(groupId, artifactId, version, qualifier)) {
68 | String fullJarDeployPath = deployTarget + File.separator + jarName;
69 | if (checkLocalCache) {
70 | try {
71 | deployFromLocalCache(groupId, artifactId, version, qualifier);
72 | searchRemoteRepo = false;
73 | } catch (Exception error) {
74 | /* ignore */
75 | }
76 | }
77 | if (searchRemoteRepo) {
78 | String urlString = generateUrlTagret(groupId, artifactId, version, jarName);
79 | ReadableByteChannel readableByteChannel = Channels.newChannel(new URL(urlString).openStream());
80 | try (FileOutputStream fileOutputStream = new FileOutputStream(fullJarDeployPath)) {
81 | fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
82 | }
83 | }
84 |
85 | DeployUtils.addToClasspath(fullJarDeployPath);
86 | }
87 | }
88 |
89 | private boolean artifactExists(String groupId, String artifactId, String version, String qualifier) {
90 | String jarName = generateArtifactName(artifactId, version, qualifier);
91 | String pathString = deployTarget + File.separator + jarName;
92 | return new File(pathString).exists();
93 | }
94 |
95 | void deployFromLocalCache(String groupId, String artifactId, String version, String qualifier)
96 | throws MalformedURLException, IOException {
97 | String jarName = generateArtifactName(artifactId, version, qualifier);
98 | String pathString = generatePathTagret(M2_CACHE, groupId, artifactId, version, jarName);
99 |
100 | ReadableByteChannel readableByteChannel = Channels
101 | .newChannel(new File(pathString).toURI().toURL().openStream());
102 | FileOutputStream fileOutputStream = new FileOutputStream(deployTarget + File.separator + jarName);
103 | fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
104 | }
105 |
106 | String generateArtifactName(String artifactId, String version, String qualifier) {
107 | StringBuilder jarName = new StringBuilder(String.format("%s-%s", artifactId, version));
108 | if (qualifier != null && !qualifier.isEmpty()) {
109 | jarName.append("-").append(qualifier);
110 | }
111 | jarName.append(".jar");
112 | return jarName.toString();
113 | }
114 |
115 | String generateUrlTagret(String groupId, String artifactId, String version, String jarName) throws IOException {
116 | if (version.endsWith("-SNAPSHOT")) {
117 | String latestSnapshotJarName = getLatestSnapshotName(groupId, artifactId, version);
118 | return String.format("%s/%s/%s/%s/%s", repoBase, groupId.replace(".", "/"), artifactId, version, latestSnapshotJarName);
119 | } else {
120 | return String.format("%s/%s/%s/%s/%s", repoBase, groupId.replace(".", "/"), artifactId, version, jarName);
121 | }
122 | }
123 |
124 | private String getLatestSnapshotName(String groupId, String artifactId, String version) throws IOException {
125 | String metadataXmlUrl = String.format("%s/%s/%s/%s/%s", repoBase, groupId.replace(".", "/"), artifactId, version, "maven-metadata.xml");
126 | ReadableByteChannel readableByteChannel = Channels.newChannel(new URL(metadataXmlUrl).openStream());
127 | try (InputStream inputStream = Channels.newInputStream(readableByteChannel)) {
128 | DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
129 | DocumentBuilder builder = builderFactory.newDocumentBuilder();
130 | Document xmlDocument = builder.parse(inputStream);
131 | XPath xPath = XPathFactory.newInstance().newXPath();
132 | String timestamp = xPath.evaluate("/metadata/versioning/snapshot/timestamp", xmlDocument);
133 | String buildNumber = xPath.evaluate("/metadata/versioning/snapshot/buildNumber", xmlDocument);
134 | String snapshotVersion = version.replace("SNAPSHOT", (timestamp + "-" + buildNumber));
135 | return String.format("%s-%s.jar", artifactId, snapshotVersion);
136 | } catch (XPathExpressionException | ParserConfigurationException | SAXException e) {
137 | throw new RuntimeException(e);
138 | }
139 | }
140 |
141 | String generatePathTagret(String base, String groupId, String artifactId, String version, String jarName) {
142 | return String.format("%s%s%s%s%s%s%s%s%s", base, File.separator, groupId.replace(".", File.separator),
143 | File.separator, artifactId, File.separator, version, File.separator, jarName);
144 | }
145 |
146 | public String getRepoBase() {
147 | return repoBase;
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/dtos/GeneratedArg.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.dtos;
16 |
17 | public class GeneratedArg {
18 | private Class clazz;
19 | private Object object;
20 |
21 | public GeneratedArg(Class clazz, Object object) {
22 | this.clazz = clazz;
23 | this.object = object;
24 | }
25 |
26 | public Class getClazz() {
27 | return clazz;
28 | }
29 |
30 | public Object getObject() {
31 | return object;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/dtos/InvocationArg.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.dtos;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl;
19 | import org.astonbitecode.j4rs.errors.InvalidArgumentException;
20 | import org.astonbitecode.j4rs.utils.Utils;
21 |
22 | public class InvocationArg implements Instance {
23 | /**
24 | * The array contents should map to a List. This is in order to allow calls of
25 | * type Arrays.asList(arg1, arg2, arg3, ...)
26 | */
27 | public static final String CONTENTS_ARRAY = "org.astonbitecode.j4rs.api.dtos.Array";
28 | private final Instance instance;
29 | private final String json;
30 | /**
31 | * If not serialized, the argument is taken straight by the Java code as Object.
32 | * Otherwise, the argument is a json document that needs to be deserialized to
33 | * an Object.
34 | */
35 | private boolean serialized;
36 | /**
37 | * The type of this argument. This is used when json objects come from Rust, in
38 | * order to be mapped to proper Java Objects.
39 | */
40 | private String className;
41 |
42 | public InvocationArg(String className, Instance instance) {
43 | this.json = null;
44 | this.className = className;
45 | this.instance = instance;
46 | this.serialized = false;
47 | }
48 |
49 | public InvocationArg(Instance instance) {
50 | this.json = null;
51 | this.className = instance.getClass().getName();
52 | this.instance = instance;
53 | this.serialized = false;
54 | }
55 |
56 | public InvocationArg(String className, String json) {
57 | this.instance = null;
58 | this.className = className;
59 | this.json = json;
60 | this.serialized = true;
61 | }
62 |
63 | public InvocationArg(String className, Object object) throws ClassNotFoundException {
64 | this.instance = new JsonInvocationImpl(object, Utils.forNameEnhanced(className));
65 | this.className = className;
66 | this.json = null;
67 | this.serialized = false;
68 | }
69 |
70 | /**
71 | * If true, the argument is taken straight by the Java code as Object. If false,
72 | * the argument is a json document that need to be deserialized to an Object.
73 | *
74 | * @return The The argFrom
75 | */
76 | public boolean isSerialized() {
77 | return serialized;
78 | }
79 |
80 | /**
81 | * The type of this argument. This is used when json objects come from Rust, in
82 | * order to be mapped to proper Java Objects.
83 | *
84 | * @return The classname
85 | */
86 | @Override
87 | public String getObjectClassName() {
88 | return className;
89 | }
90 |
91 | public Instance getInstance() {
92 | if (isSerialized()) {
93 | throw new InvalidArgumentException(
94 | "This InvocationArg of class " + className + " is created by Rust code.");
95 | }
96 | return instance;
97 | }
98 |
99 | public String getJson() {
100 | if (!isSerialized()) {
101 | throw new InvalidArgumentException(
102 | "This InvocationArg of class " + className + " is created by Java code.");
103 | }
104 | return json;
105 | }
106 |
107 | @Override
108 | public String toString() {
109 | return "classname:" + this.className + ", serialized:" + this.serialized + ", json:" + this.json + ", instance:"
110 | + this.instance;
111 | }
112 |
113 | @Override
114 | public Object getObject() {
115 | return getInstance() != null ? getInstance().getObject() : null;
116 | }
117 |
118 | @Override
119 | public Class> getObjectClass() {
120 | return getInstance() != null ? getInstance().getObjectClass() : null;
121 | }
122 |
123 | @Override
124 | public Instance invoke(String methodName, InvocationArg... args) {
125 | return getInstance() != null ? getInstance().invoke(methodName, args) : null;
126 | }
127 |
128 | @Override
129 | public Instance invokeStatic(String methodName, InvocationArg... args) {
130 | return getInstance() != null ? getInstance().invokeStatic(methodName, args) : null;
131 | }
132 |
133 | @Override
134 | public void invokeAsyncToChannel(long channelAddress, String methodName, InvocationArg... args) {
135 | if (getInstance() != null) {
136 | getInstance().invokeAsyncToChannel(channelAddress, methodName, args);
137 | }
138 | }
139 |
140 | @Override
141 | public void invokeToChannel(long channelAddress, String methodName, InvocationArg... args) {
142 | if (getInstance() != null) {
143 | getInstance().invokeToChannel(channelAddress, methodName, args);
144 | }
145 | }
146 |
147 | @Override
148 | public void initializeCallbackChannel(long channelAddress) {
149 | if (getInstance() != null) {
150 | getInstance().initializeCallbackChannel(channelAddress);
151 | }
152 | }
153 |
154 | @Override
155 | public Instance field(String fieldName) {
156 | return getInstance() != null ? getInstance().field(fieldName) : null;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/dtos/InvocationArgGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.dtos;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.api.ObjectValue;
19 | import org.astonbitecode.j4rs.api.value.JsonValueFactory;
20 | import org.astonbitecode.j4rs.errors.InvalidArgumentException;
21 | import org.astonbitecode.j4rs.utils.Utils;
22 |
23 | import java.util.Arrays;
24 |
25 | public class InvocationArgGenerator {
26 | public GeneratedArg[] generateArgObjects(InvocationArg[] args) {
27 | GeneratedArg[] generatedArgArr = Arrays.stream(args).map(invArg -> {
28 | GeneratedArg generatedArg;
29 | if (invArg.isSerialized()) {
30 | ObjectValue objValue = JsonValueFactory.create(invArg.getJson(), invArg.getObjectClassName());
31 | try {
32 | // If the invArg is an array, use its type class. In other cases, use the
33 | // forNameEnhanced to retrieve its class.
34 | generatedArg = invArg.getObjectClassName().equals(InvocationArg.CONTENTS_ARRAY)
35 | ? new GeneratedArg(objValue.getObjectClass(), objValue.getObject())
36 | : new GeneratedArg(Utils.forNameEnhanced(invArg.getObjectClassName()),
37 | objValue.getObject());
38 | } catch (ClassNotFoundException cnfe) {
39 | throw new InvalidArgumentException("Cannot parse InvocationArgument ", cnfe);
40 | }
41 | } else {
42 | Instance inv = invArg.getInstance();
43 | try {
44 | generatedArg = new GeneratedArg(
45 | inv != null ? inv.getObjectClass() : Utils.forNameEnhanced(invArg.getObjectClassName()),
46 | inv != null ? inv.getObject() : null);
47 | } catch (ClassNotFoundException cnfe) {
48 | System.out.println("j4rs Warning! ClassNotFoundException for " + invArg.getObjectClassName()
49 | + " Using java.lang.Object instead...");
50 | generatedArg = new GeneratedArg(Object.class, null);
51 | }
52 | }
53 | return generatedArg;
54 | }).toArray(i -> new GeneratedArg[i]);
55 |
56 | return generatedArgArr;
57 | }
58 |
59 | public static GeneratedArg argOf(Class clazz, Object object) {
60 | return new GeneratedArg(clazz, object);
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/invocation/InstanceGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import java.lang.reflect.Type;
18 | import java.util.HashMap;
19 | import java.util.Iterator;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.ServiceLoader;
23 |
24 | import org.astonbitecode.j4rs.api.Instance;
25 | import org.astonbitecode.j4rs.api.services.delegates.InstanceGeneratorDelegate;
26 | import org.astonbitecode.j4rs.errors.InvocationException;
27 |
28 | public class InstanceGenerator {
29 | private static Map delegates = new HashMap<>();
30 | static {
31 | ServiceLoader loader = ServiceLoader.load(InstanceGeneratorDelegate.class);
32 | Iterator discoveredDelegates = loader.iterator();
33 | while (discoveredDelegates.hasNext()) {
34 | InstanceGeneratorDelegate d = discoveredDelegates.next();
35 | delegates.put(d.getClass().getCanonicalName(), d);
36 | }
37 | }
38 |
39 | public static Instance create(T instance, Class clazz, List classGenTypes) {
40 | JsonInvocationImpl jsonInvocation = new JsonInvocationImpl(instance, clazz, classGenTypes);
41 | if (shouldRunInFxThread(jsonInvocation.getObjectClass())) {
42 | return getProxiedForJavaFx(jsonInvocation);
43 | } else {
44 | return jsonInvocation;
45 | }
46 | }
47 |
48 | public static Instance create(T instance, Class clazz) {
49 | JsonInvocationImpl jsonInvocation = new JsonInvocationImpl(instance, clazz);
50 | if (shouldRunInFxThread(jsonInvocation.getObjectClass())) {
51 | return getProxiedForJavaFx(jsonInvocation);
52 | } else {
53 | return jsonInvocation;
54 | }
55 | }
56 |
57 | public static Instance create(Class clazz) {
58 | JsonInvocationImpl jsonInvocation = new JsonInvocationImpl(clazz);
59 | if (shouldRunInFxThread(jsonInvocation.getObjectClass())) {
60 | return getProxiedForJavaFx(jsonInvocation);
61 | } else {
62 | return jsonInvocation;
63 | }
64 | }
65 |
66 | private static Instance getProxiedForJavaFx(Instance instance) {
67 | InstanceGeneratorDelegate delegate = delegates
68 | .get("org.astonbitecode.j4rs.api.invocation.JavaFxInstanceGeneratorDelegate");
69 | if (delegate == null) {
70 | throw new InvocationException(
71 | "Attempted to proxy Instance in order to be executed in FX thread, but delegate is not configured. Please make sure you have j4rs-javafx in the classpath");
72 | } else {
73 | return delegate.proxy(instance);
74 | }
75 | }
76 |
77 | private static boolean shouldRunInFxThread(Class> clazz) {
78 | String className = clazz.getName();
79 | return className.startsWith("javafx") || (className.startsWith("org.astonbitecode.j4rs.api.jfx")
80 | && !className.startsWith("org.astonbitecode.j4rs.api.jfx.FxApplication"));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/invocation/NativeCallbackToRustChannelSupport.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.errors.InvocationException;
19 | import org.astonbitecode.j4rs.rust.RustPointer;
20 |
21 | import java.util.Optional;
22 |
23 | /**
24 | * Performs native callbacks to Rust channels
25 | */
26 | public class NativeCallbackToRustChannelSupport {
27 | private static native int docallbacktochannel(long channelPointerAddress, Instance inv);
28 |
29 | private Optional channelPointerOpt = Optional.empty();
30 |
31 | static void initialize(String libname) {
32 | try {
33 | System.loadLibrary(libname);
34 | } catch (UnsatisfiedLinkError error) {
35 | System.err.println(
36 | "The Callbacks are not initialized because the j4rs lib was not found. You may ignore this error if you don't use callbacks.");
37 | error.printStackTrace();
38 | }
39 | }
40 |
41 | /**
42 | * Perform a callback
43 | *
44 | * @param obj The {@link Object} to pass in the callback.
45 | */
46 | public void doCallback(Object obj) {
47 | if (channelPointerOpt.isPresent() && obj != null) {
48 | docallbacktochannel(channelPointerOpt.get().getAddress(), InstanceGenerator.create(obj, obj.getClass()));
49 | } else {
50 | throw new InvocationException(
51 | "Cannot do callback. Please make sure that you don't try to access this method while being in the constructor of your class (that extends NativeCallbackSupport)");
52 | }
53 | }
54 |
55 | final void initPointer(RustPointer p) {
56 | this.channelPointerOpt = Optional.of(p);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/invocation/NativeCallbackToRustFutureSupport.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.invocation;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.api.value.NullObject;
19 | import org.astonbitecode.j4rs.errors.InvocationException;
20 | import org.astonbitecode.j4rs.rust.RustPointer;
21 |
22 | import java.io.PrintWriter;
23 | import java.io.StringWriter;
24 | import java.util.Optional;
25 |
26 | /**
27 | * Performs native callbacks to Rust channels that are transformed to Rust
28 | * Futures
29 | */
30 | class NativeCallbackToRustFutureSupport {
31 | private static native int docallbacktochannel(long channelPointerAddress, Instance inv);
32 |
33 | private static native int failcallbacktochannel(long channelPointerAddress, String stacktrace);
34 |
35 | private Optional channelPointerOpt = Optional.empty();
36 |
37 | static void initialize(String libname) {
38 | try {
39 | System.loadLibrary(libname);
40 | } catch (UnsatisfiedLinkError error) {
41 | System.err.println(
42 | "The Callbacks are not initialized because the j4rs lib was not found. You may ignore this error if you don't use callbacks.");
43 | error.printStackTrace();
44 | }
45 | }
46 |
47 | /**
48 | * Perform a callback to signal successful operation
49 | *
50 | * @param obj The {@link Object} to pass in the callback.
51 | */
52 | public void doCallbackSuccess(Object obj) {
53 | if (channelPointerOpt.isPresent()) {
54 | if (obj != null) {
55 | docallbacktochannel(channelPointerOpt.get().getAddress(),
56 | InstanceGenerator.create(obj, obj.getClass()));
57 | } else {
58 | docallbacktochannel(channelPointerOpt.get().getAddress(),
59 | InstanceGenerator.create(null, NullObject.class));
60 | }
61 | } else {
62 | throw new InvocationException(
63 | "Cannot do callback. Please make sure that you don't try to access this method while being in the constructor of your class (that extends NativeCallbackToRustFutureSupport)");
64 | }
65 | }
66 |
67 | /**
68 | * Perform a callback to signal failure
69 | *
70 | * @param error The error
71 | */
72 | public void doCallbackFailure(Throwable error) {
73 | if (channelPointerOpt.isPresent() && error != null) {
74 | StringWriter sw = new StringWriter();
75 | PrintWriter pw = new PrintWriter(sw);
76 | error.printStackTrace(pw);
77 | String stringStackTrace = sw.toString();
78 | failcallbacktochannel(channelPointerOpt.get().getAddress(), stringStackTrace);
79 | } else {
80 | throw new InvocationException(
81 | "Cannot do callback for failure. Please make sure that you don't try to access this method while being in the constructor of your class (that extends NativeCallbackSupport). The failure was: ",
82 | error);
83 | }
84 | }
85 |
86 | final void initPointer(RustPointer p) {
87 | this.channelPointerOpt = Optional.of(p);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/java2rust/Java2RustUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.java2rust;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 | import org.astonbitecode.j4rs.api.invocation.JsonInvocationImpl;
19 |
20 | public class Java2RustUtils {
21 | @SuppressWarnings("unchecked")
22 | public static Instance createInstance(T obj) {
23 | return new JsonInvocationImpl(obj, (Class) obj.getClass());
24 | }
25 |
26 | @SuppressWarnings("unchecked")
27 | public static T getObjectCasted(Instance instance) {
28 | return (T) instance.getOrDeserializeJavaObject();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/services/delegates/InstanceGeneratorDelegate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.services.delegates;
16 |
17 | import org.astonbitecode.j4rs.api.Instance;
18 |
19 | /**
20 | * Delegates the generation of Intsances, by creating Instances proxies.
21 | * This is needed for example to execute code in the JavaFX thread.
22 | */
23 | public interface InstanceGeneratorDelegate {
24 | /**
25 | * Creates a proxied instance
26 | * @param The type of the Object the Instance contains
27 | * @param instance The Instance
28 | * @return A proxied Instance
29 | */
30 | Instance proxy(Instance instance);
31 | }
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/services/json/Codec.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package org.astonbitecode.j4rs.api.services.json;
17 |
18 | import org.astonbitecode.j4rs.api.services.json.exceptions.JsonCodecException;
19 |
20 | /**
21 | * Codec to perform JSON encoding and decoding
22 | */
23 | public interface Codec {
24 |
25 | /**
26 | * Deocde a json String to an Object
27 | * @param json The json
28 | * @param className A class name
29 | * @return An Object
30 | * @param The type of the object
31 | * @throws JsonCodecException In case something goes wrong
32 | */
33 | T decode(String json, String className) throws JsonCodecException;
34 |
35 | /**
36 | * Encode an object to json String
37 | * @param obj The Object to encode
38 | * @return A json String
39 | * @param The type of the Object
40 | * @throws JsonCodecException In case something goes wrong
41 | */
42 | String encode(T obj) throws JsonCodecException;
43 |
44 | /**
45 | * Decodes a json String to an array of Objects
46 | * @param json The json String to decode
47 | * @return An array of Objects
48 | * @throws JsonCodecException In case something goes wrong
49 | */
50 | Object[] decodeArrayContents(String json) throws JsonCodecException;
51 | }
52 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/services/json/exceptions/JsonCodecException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.services.json.exceptions;
16 |
17 | public class JsonCodecException extends RuntimeException {
18 | public JsonCodecException(String message) {
19 | super(message);
20 | }
21 |
22 | public JsonCodecException(String message, Exception nestedException) {
23 | super(message, nestedException);
24 | }
25 |
26 | public JsonCodecException(Exception nestedException) {
27 | super(nestedException);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/value/JsonValueFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.value;
16 |
17 | import org.astonbitecode.j4rs.api.JsonValue;
18 |
19 | public class JsonValueFactory {
20 | public static JsonValue create(T obj) {
21 | return obj != null ? new JsonValueImpl(obj) : new NullJsonValueImpl();
22 | }
23 |
24 | public static JsonValue create(String json, String className) {
25 | return new JsonValueImpl(json, className);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/value/JsonValueImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.value;
16 |
17 | import org.astonbitecode.j4rs.api.JsonValue;
18 | import org.astonbitecode.j4rs.api.dtos.InvocationArg;
19 | import org.astonbitecode.j4rs.api.services.json.Codec;
20 | import org.astonbitecode.j4rs.api.services.json.exceptions.JsonCodecException;
21 | import org.astonbitecode.j4rs.json.JsonCodecService;
22 |
23 | public class JsonValueImpl implements JsonValue {
24 | private final Codec jsonCodec;
25 | private Object obj;
26 | private String json;
27 | @SuppressWarnings("unused")
28 | private String className;
29 |
30 | JsonValueImpl(T obj) {
31 | this.jsonCodec = JsonCodecService.getJsonCodec();
32 | this.obj = obj;
33 | try {
34 | this.json = jsonCodec.encode(obj);
35 | } catch (JsonCodecException error) {
36 | throw new JsonCodecException(
37 | "While creating JsonValueCallbackImpl for instance of " + obj.getClass().getName(), error);
38 | }
39 | this.className = obj.getClass().getName();
40 | }
41 |
42 | JsonValueImpl(String json, String className) {
43 | this.jsonCodec = JsonCodecService.getJsonCodec();
44 | try {
45 | if (className.equals(InvocationArg.CONTENTS_ARRAY)) {
46 | this.obj = jsonCodec.decodeArrayContents(json);
47 | } else {
48 | this.obj = jsonCodec.decode(json, className);
49 | }
50 | } catch (JsonCodecException error) {
51 | throw new JsonCodecException("While creating JsonValueCallbackImpl: Could not decode " + json, error);
52 | }
53 | this.json = json;
54 | this.className = className;
55 | }
56 |
57 | @Override
58 | public String getJson() {
59 | return this.json;
60 | }
61 |
62 | @Override
63 | public Object getObject() {
64 | return this.obj;
65 | }
66 |
67 | @Override
68 | public Class> getObjectClass() {
69 | return this.obj.getClass();
70 | }
71 |
72 | @Override
73 | public String getObjectClassName() {
74 | return this.obj.getClass().getName();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/value/NullJsonValueImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.value;
16 |
17 | import org.astonbitecode.j4rs.api.JsonValue;
18 | import org.astonbitecode.j4rs.api.ObjectValue;
19 |
20 | public class NullJsonValueImpl implements JsonValue, ObjectValue {
21 | private Object obj;
22 | private String json;
23 | @SuppressWarnings("unused")
24 | private String className;
25 |
26 | NullJsonValueImpl() {
27 | this.obj = null;
28 | this.json = "null";
29 | this.className = NullObject.class.getName();
30 | }
31 |
32 | @Override
33 | public String getJson() {
34 | return this.json;
35 | }
36 |
37 | @Override
38 | public Object getObject() {
39 | return this.obj;
40 | }
41 |
42 | @Override
43 | public Class> getObjectClass() {
44 | return NullObject.class;
45 | }
46 |
47 | @Override
48 | public String getObjectClassName() {
49 | return NullObject.class.getName();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/api/value/NullObject.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.api.value;
16 |
17 | public class NullObject {
18 | }
19 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/errors/InstantiationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.errors;
16 |
17 | public class InstantiationException extends RuntimeException {
18 | public InstantiationException(String message, Throwable nestedException) {
19 | super(message, nestedException);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/errors/InvalidArgumentException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.errors;
16 |
17 | public class InvalidArgumentException extends RuntimeException {
18 | public InvalidArgumentException(String message) {
19 | super(message);
20 | }
21 |
22 | public InvalidArgumentException(String message, Throwable inner) {
23 | super(message, inner);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/errors/InvocationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.errors;
16 |
17 | public class InvocationException extends RuntimeException {
18 | public InvocationException(String message, Throwable nestedException) {
19 | super(message, nestedException);
20 | }
21 |
22 | public InvocationException(String message) {
23 | super(message);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/java/src/main/java/org/astonbitecode/j4rs/json/JacksonCodec.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 astonbitecode
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.astonbitecode.j4rs.json;
16 |
17 | import com.fasterxml.jackson.core.JsonProcessingException;
18 | import com.fasterxml.jackson.core.type.TypeReference;
19 | import com.fasterxml.jackson.databind.ObjectMapper;
20 | import org.astonbitecode.j4rs.api.services.json.Codec;
21 | import org.astonbitecode.j4rs.api.services.json.exceptions.JsonCodecException;
22 | import org.astonbitecode.j4rs.utils.Utils;
23 |
24 | import java.io.IOException;
25 | import java.util.Arrays;
26 | import java.util.Map;
27 |
28 | public class JacksonCodec implements Codec {
29 | private static final String RUST_FIELD = "Rust";
30 | private static final String JSON_FIELD = "json";
31 | private static final String CLASS_NAME_FIELD = "class_name";
32 | private ObjectMapper mapper = new ObjectMapper();
33 | TypeReference