diff --git a/.github/workflows/BuildAndRun.yml b/.github/workflows/BuildAndRun.yml
index becdedd00..022240df0 100644
--- a/.github/workflows/BuildAndRun.yml
+++ b/.github/workflows/BuildAndRun.yml
@@ -10,21 +10,21 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
-
+
- name: Set SHORT_HASH
run: |
- echo "::set-output name=VALUE::${LONG_HASH:0:8}"
- echo "RELEASE_TAG=${LONG_HASH:0:8}-$(TZ=UTC-8 date +"%Y.%m.%d")" >> $GITHUB_ENV
+ echo "::set-output name=VALUE::${LONG_HASH:0:8}"
+ echo "RELEASE_TAG=${LONG_HASH:0:8}-$(TZ=UTC-8 date +"%Y.%m.%d")" >> $GITHUB_ENV
id: short_hash
env:
- LONG_HASH: ${{ github.sha }}
+ LONG_HASH: ${{ github.sha }}
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
-
+
- name: Set up Maven
uses: stCarolas/setup-maven@v4.5
with:
@@ -33,34 +33,31 @@ jobs:
- name: Create output folder
run: mkdir BuildOutput
+# - name: Build flyfly project
+# working-directory: ./FlySpring/flyfly
+# run: mvn clean package
- - name: Build flyfly project
- working-directory: ./FlySpring/flyfly
- run: mvn clean package
-
-
-
- - name: Copy flyfly JAR to Examples folder and rename
- run: cp ./FlySpring/flyfly/target/flyfly-0.0.1-SNAPSHOT.jar ././BuildOutput/flyfly.jar
+# - name: Copy flyfly JAR to Examples folder and rename
+# run: cp ./FlySpring/flyfly/target/flyfly-0.0.1-SNAPSHOT.jar ././BuildOutput/flyfly.jar
- name: Build edgechain-app project
working-directory: ./FlySpring/edgechain-app
-# run: mvn -Djavacpp.platform=linux-x86_64 clean package -DskipTests
+ # run: mvn -Djavacpp.platform=linux-x86_64 clean package -DskipTests
run: mvn clean package -DskipTests
-
+
- name: Run edgechain testcases
working-directory: ./FlySpring/edgechain-app
run: mvn test
- name: Copy edgechain-app JAR to Examples folder
- run: cp ./FlySpring/edgechain-app/target/edgechain-app-1.0.0.jar ./BuildOutput/
+ run: cp ./FlySpring/edgechain-app/target/edgechain.jar ./BuildOutput/
- name: Upload Examples folder as artifact
uses: actions/upload-artifact@v3
with:
name: Output
path: ./BuildOutput/
-
+
release:
name: Release jar
needs: build_and_run
@@ -75,24 +72,24 @@ jobs:
- name: Display structure of downloaded files
run: ls -R
-# - name: Create Release
-# id: create_release
-# uses: actions/create-release@v1.1.4
-# env:
-# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-# with:
-# tag_name: ${{ github.ref }}
-# release_name: ${{ github.ref }}
-# - name: Upload Release jar
-# id: upload_release_asset
-# uses: actions/upload-release-asset@v1.0.1
-# env:
-# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-# with:
-# upload_url: ${{ steps.create_release.outputs.upload_url }}
-# asset_path: Examples/
-# asset_name: Examples
-# asset_content_type: application/zip
+ # - name: Create Release
+ # id: create_release
+ # uses: actions/create-release@v1.1.4
+ # env:
+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # with:
+ # tag_name: ${{ github.ref }}
+ # release_name: ${{ github.ref }}
+ # - name: Upload Release jar
+ # id: upload_release_asset
+ # uses: actions/upload-release-asset@v1.0.1
+ # env:
+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # with:
+ # upload_url: ${{ steps.create_release.outputs.upload_url }}
+ # asset_path: Examples/
+ # asset_name: Examples
+ # asset_content_type: application/zip
- name: 'Get variables'
id: vars
run: |
@@ -100,10 +97,10 @@ jobs:
- name: Release
uses: softprops/action-gh-release@v1
with:
- tag_name: ${{ env.RELEASE_TAG }}
-# body: 🚀 Automated build
- files: |
- ./Output/**/*.*
-
- # tag_name: ${{needs.build_and_run.steps.short_hash.outputs.VALUE}}
+ tag_name: ${{ env.RELEASE_TAG }}
+ # body: 🚀 Automated build
+ files: |
+ ./Output/**/*.*
+
+ # tag_name: ${{needs.build_and_run.steps.short_hash.outputs.VALUE}}
diff --git a/FlySpring/edgechain-app/.gitignore b/FlySpring/edgechain-app/.gitignore
index 076818c37..138525d2a 100644
--- a/FlySpring/edgechain-app/.gitignore
+++ b/FlySpring/edgechain-app/.gitignore
@@ -34,3 +34,4 @@ build/
### VS Code ###
.vscode/
+/src/main/resources/jbang.jar
diff --git a/FlySpring/edgechain-app/pom.xml b/FlySpring/edgechain-app/pom.xml
index 0d9aa5fb7..f790cf5bc 100644
--- a/FlySpring/edgechain-app/pom.xml
+++ b/FlySpring/edgechain-app/pom.xml
@@ -10,7 +10,6 @@
jar
17
- 2022.0.3
17
17
@@ -36,6 +35,12 @@
spring-boot-starter-webflux
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
redis.clients
jedis
@@ -78,18 +83,6 @@
2.3.1
-
- com.zaxxer
- HikariCP
- 5.0.1
-
-
-
-
- org.springframework
- spring-jdbc
-
-
com.squareup.retrofit2
@@ -241,6 +234,35 @@
0.4.2
+
+
+ info.picocli
+ picocli-spring-boot-starter
+ 4.7.0
+
+
+
+ net.lingala.zip4j
+ zip4j
+ 2.11.3
+
+
+
+ org.zeroturnaround
+ zt-exec
+ 1.12
+
+
+
+ org.testcontainers
+ testcontainers
+ 1.17.6
+
+
+
+ org.testcontainers
+ postgresql
+
org.springframework.boot
@@ -263,13 +285,6 @@
import
-
- org.springframework.cloud
- spring-cloud-dependencies
- ${spring-cloud.version}
- pom
- import
-
@@ -314,6 +329,7 @@
shade
+ edgechain
@@ -326,14 +342,56 @@
-
-
-
+
+ com.edgechain.EdgeChainApplication
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.8
+
+
+ download-and-unpack-jbang
+ generate-resources
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/EdgeChainApplication.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/EdgeChainApplication.java
new file mode 100644
index 000000000..dd29eb5cd
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/EdgeChainApplication.java
@@ -0,0 +1,55 @@
+package com.edgechain;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
+
+import java.net.URL;
+import java.nio.file.Paths;
+
+@SpringBootApplication
+public class EdgeChainApplication {
+
+ private static final Logger logger = LoggerFactory.getLogger(EdgeChainApplication.class);
+
+ public static void main(String[] args) {
+
+ System.setProperty("jar.name", getJarFileName(EdgeChainApplication.class));
+
+ logger.info("Executed jar file: "+System.getProperty("jar.name"));
+
+ SpringApplication springApplication =
+ new SpringApplicationBuilder()
+ .sources(EdgeChainApplication.class).web(WebApplicationType.NONE)
+ .build();
+
+ springApplication.run(args);
+ }
+
+ @Bean(name = "mvcHandlerMappingIntrospector")
+ public HandlerMappingIntrospector mvcHandlerMappingIntrospector() {
+ return new HandlerMappingIntrospector();
+ }
+
+ private static String getJarFileName(Class> clazz) {
+ URL classResource = clazz.getResource(clazz.getSimpleName() + ".class");
+ if (classResource == null) {
+ throw new RuntimeException("class resource is null");
+ }
+ String url = classResource.toString();
+ if (url.startsWith("jar:file:")) {
+ String path = url.replaceAll("^jar:(file:.*[.]jar)!/.*", "$1");
+ try {
+ return Paths.get(new URL(path).toURI()).toString();
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid jar file");
+ }
+ }
+ throw new RuntimeException("Invalid jar file");
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/impl/PostgreSQLHistoryContextClient.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/impl/PostgreSQLHistoryContextClient.java
index 32355c59c..08b5e7538 100644
--- a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/impl/PostgreSQLHistoryContextClient.java
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/impl/PostgreSQLHistoryContextClient.java
@@ -9,7 +9,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Objects;
@@ -20,7 +22,9 @@ public class PostgreSQLHistoryContextClient
private Logger logger = LoggerFactory.getLogger(this.getClass());
- @Autowired private PostgreSQLHistoryContextRepository repository;
+ @Autowired private PostgreSQLHistoryContextRepository historyContextRepository;
+
+ @Autowired private JdbcTemplate jdbcTemplate;
private static final String PREFIX = "historycontext:";
@@ -34,12 +38,10 @@ public EdgeChain create(String id, PostgreSQLHistoryContextEndpo
if (Objects.isNull(id) || id.isEmpty())
throw new RuntimeException("Postgres history_context id cannot be empty or null");
- this.repository.createTable(); // Create Table IF NOT EXISTS;
+ this.createTable(); // Create Table IF NOT EXISTS;
HistoryContext context = new HistoryContext(PREFIX + id, "", LocalDateTime.now());
- this.repository.insert(context);
-
- emitter.onNext(context);
+ emitter.onNext(historyContextRepository.save(context));
emitter.onComplete();
} catch (final Exception e) {
@@ -61,12 +63,12 @@ public EdgeChain put(
String input = response.replaceAll("'", "");
historyContext.setResponse(input);
- this.repository.update(historyContext);
-
+ HistoryContext returnValue = this.historyContextRepository.save(historyContext);
logger.info(String.format("%s is updated", id));
- emitter.onNext(historyContext);
+ emitter.onNext(returnValue);
emitter.onComplete();
+
} catch (final Exception e) {
emitter.onError(e);
}
@@ -81,7 +83,7 @@ public EdgeChain get(String id, PostgreSQLHistoryContextEndpoint
emitter -> {
try {
emitter.onNext(
- this.repository
+ this.historyContextRepository
.findById(id)
.orElseThrow(
() ->
@@ -101,7 +103,10 @@ public EdgeChain delete(String id, PostgreSQLHistoryContextEndpoint endp
Observable.create(
emitter -> {
try {
- this.repository.delete(id);
+
+ HistoryContext historyContext = this.get(id, null).get();
+ this.historyContextRepository.delete(historyContext);
+
emitter.onNext("");
emitter.onComplete();
} catch (final Exception e) {
@@ -110,4 +115,11 @@ public EdgeChain delete(String id, PostgreSQLHistoryContextEndpoint endp
}),
endpoint);
}
+
+ @Transactional
+ public void createTable() {
+ jdbcTemplate.execute(
+ "CREATE TABLE IF NOT EXISTS history_context (id TEXT PRIMARY KEY, response TEXT, created_at"
+ + " timestamp)");
+ }
}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/repositories/PostgreSQLHistoryContextRepository.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/repositories/PostgreSQLHistoryContextRepository.java
index b296c03fe..9df6a0ee8 100644
--- a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/repositories/PostgreSQLHistoryContextRepository.java
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/client/repositories/PostgreSQLHistoryContextRepository.java
@@ -3,6 +3,7 @@
import com.edgechain.lib.context.client.impl.jdbc.HistoryContextRowMapper;
import com.edgechain.lib.context.domain.HistoryContext;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@@ -11,45 +12,7 @@
import java.util.Optional;
@Repository
-public class PostgreSQLHistoryContextRepository {
+public interface PostgreSQLHistoryContextRepository extends JpaRepository {
- @Autowired private JdbcTemplate jdbcTemplate;
- @Transactional
- public void createTable() {
- jdbcTemplate.execute(
- "CREATE TABLE IF NOT EXISTS history_context (id TEXT PRIMARY KEY, response TEXT, created_at"
- + " timestamp)");
- }
-
- @Transactional
- public void insert(HistoryContext context) {
- jdbcTemplate.execute(
- String.format(
- "INSERT INTO history_context (id, response, created_at) values ('%s','%s', '%s')",
- context.getId(), context.getResponse(), context.getCreatedAt()));
- }
-
- @Transactional
- public void update(HistoryContext context) {
- jdbcTemplate.execute(
- String.format(
- "INSERT INTO history_context (id, response) values ('%s','%s')\n"
- + " ON CONFLICT (id) DO UPDATE SET response = EXCLUDED.response;",
- context.getId(), context.getResponse()));
- }
-
- @Transactional(readOnly = true)
- public Optional findById(String id) {
- String sql = String.format("select * from history_context where id='%s'", id);
- List contextList = jdbcTemplate.query(sql, new HistoryContextRowMapper());
-
- if (contextList.size() > 0) return Optional.ofNullable(contextList.get(0));
- else return Optional.empty();
- }
-
- @Transactional
- public void delete(String id) {
- jdbcTemplate.execute(String.format("delete from history_context where id='%s'", id));
- }
}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/domain/HistoryContext.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/domain/HistoryContext.java
index 8d5c3886e..86cc1b29c 100644
--- a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/domain/HistoryContext.java
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/context/domain/HistoryContext.java
@@ -1,12 +1,19 @@
package com.edgechain.lib.context.domain;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
import java.io.Serializable;
import java.time.LocalDateTime;
+@Entity(name = "HistoryContext")
+@Table(name = "history_context")
public class HistoryContext implements Serializable {
private static final long serialVersionUID = 2819947915596690671L;
+ @Id
private String id;
private String response;
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/CustomApplicationRunner.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/CustomApplicationRunner.java
new file mode 100644
index 000000000..b03c8f945
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/CustomApplicationRunner.java
@@ -0,0 +1,25 @@
+package com.edgechain.lib.flyfly;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.*;
+import org.springframework.stereotype.Component;
+import picocli.CommandLine;
+import picocli.CommandLine.IFactory;
+
+@Component
+public class CustomApplicationRunner implements CommandLineRunner, ExitCodeGenerator {
+ @Autowired private FlyflyCommand runCommand;
+ @Autowired private IFactory factory; // auto-configured to inject PicocliSpringFactory
+
+ private int exitCode;
+
+ @Override
+ public void run(String... args) throws Exception {
+ exitCode = new CommandLine(runCommand, factory).execute(args);
+ }
+
+ @Override
+ public int getExitCode() {
+ return exitCode;
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/FlyflyCommand.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/FlyflyCommand.java
new file mode 100644
index 000000000..313ce25a0
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/FlyflyCommand.java
@@ -0,0 +1,19 @@
+package com.edgechain.lib.flyfly;
+
+import com.edgechain.lib.flyfly.commands.format.FormatCommand;
+import com.edgechain.lib.flyfly.commands.jbang.JbangCommand;
+import com.edgechain.lib.flyfly.commands.run.RunCommand;
+import org.springframework.stereotype.Component;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+@Component
+@Command(
+ name = "edgechain",
+ subcommands = {
+ RunCommand.class,
+ FormatCommand.class,
+ JbangCommand.class,
+ CommandLine.HelpCommand.class
+ })
+public class FlyflyCommand {}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/FormatCommand.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/FormatCommand.java
new file mode 100644
index 000000000..6b21492a3
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/FormatCommand.java
@@ -0,0 +1,29 @@
+package com.edgechain.lib.flyfly.commands.format;
+
+import com.edgechain.lib.flyfly.utils.ProjectTypeChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import picocli.CommandLine.Command;
+
+@Component
+@Command(name = "format", description = "Format code with Spotless", hidden = true)
+public class FormatCommand implements Runnable {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired Formatter formatter;
+ @Autowired
+ ProjectTypeChecker projectTypeChecker;
+
+ @Override
+ public void run() {
+
+ if (projectTypeChecker.isGradleProject()) formatter.format();
+ else {
+ log.error("Couldn't find build.gradle");
+ log.error("Please try again inside the project directory");
+ }
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/Formatter.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/Formatter.java
new file mode 100644
index 000000000..cd2cdff97
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/format/Formatter.java
@@ -0,0 +1,38 @@
+package com.edgechain.lib.flyfly.commands.format;
+
+import com.edgechain.lib.flyfly.utils.ProjectSetup;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Formatter {
+ @Autowired
+ ProjectSetup projectSetup;
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ void format() {
+ try {
+ log.info("Checking formatting configuration");
+ if (!projectSetup.formatScriptExists()) {
+ log.info("Configuring Spotless");
+ projectSetup.addFormatScript();
+ }
+ log.info("Running Spotless");
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS)
+ command = new String[] {"cmd", "/c", "gradlew.bat -I .flyfly/format.gradle spotlessApply"};
+ else
+ command = new String[] {"bash", "-c", "./gradlew -I .flyfly/format.gradle spotlessApply"};
+
+ ProcessBuilder pb = new ProcessBuilder(command);
+ pb.inheritIO();
+ pb.start().waitFor();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/jbang/JbangCommand.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/jbang/JbangCommand.java
new file mode 100644
index 000000000..0e7f66357
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/jbang/JbangCommand.java
@@ -0,0 +1,146 @@
+package com.edgechain.lib.flyfly.commands.jbang;
+
+import java.io.*;
+import java.util.HashMap;
+
+import org.springframework.stereotype.Component;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Parameters;
+
+@Component
+@Command(name = "jbang", description = "Activate jbang through the jar placed in resources. Ignore if your application is executed.")
+public class JbangCommand implements Runnable {
+
+ @Parameters(description = "Java file to be executed with jbang")
+ private String javaFile;
+
+// @Parameters(description = "ClassPath Jar to be used")
+// private String classPathJar;
+
+ @Override
+ public void run() {
+ String resourcePath = "/jbang.jar";
+ try {
+ File jarFile = extractFileFromResources(resourcePath);
+ if (jarFile != null) {
+ runJbang(jarFile, javaFile, System.getProperty("jar.name"));
+ } else {
+ System.out.println("Could not find jbang.jar in resources.");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private File extractFileFromResources(String resourcePath) throws IOException {
+ InputStream inputStream = getClass().getResourceAsStream(resourcePath);
+ if (inputStream == null) {
+ return null;
+ }
+ File jarFile = File.createTempFile("jbang", ".jar");
+ jarFile.deleteOnExit();
+ try (FileOutputStream outputStream = new FileOutputStream(jarFile)) {
+ inputStream.transferTo(outputStream);
+ }
+ return jarFile;
+ }
+
+ private void runJbang(File jarFile, String javaFile, String classPathJar) {
+ try {
+ // Step One: Execute the initial command to get the classpath
+ ProcessBuilder pb =
+ new ProcessBuilder(
+ "java",
+ "-cp",
+ jarFile.getAbsolutePath(),
+ "dev.jbang.Main",
+ "--cp",
+ classPathJar,
+ javaFile);
+ pb.redirectErrorStream(true);
+ Process process = pb.start();
+ BufferedReader bufferedReader =
+ new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+ String classPath = extractClassPathFromOutput(bufferedReader);
+ String mainClass;
+
+ String[] filePath;
+
+ String platformName = System.getProperty("os.name");
+ if (platformName.contains("Windows")) {
+ filePath = classPath.split(";");
+ } else {
+ filePath = classPath.split(":");
+ }
+
+ File file = new File(filePath[0]);
+ String filename = file.getName().split("\\.")[0];
+ mainClass = String.format("com.edgechain.%s", filename);
+
+ System.out.println("Extracted Filename: " + filename);
+ System.out.println("Main Class: " + mainClass);
+
+ process.waitFor();
+
+ // Step Two: Execute the final command with the extracted classpath
+ if (!classPath.isEmpty() && mainClass != null && !mainClass.isEmpty()) {
+ runJavaWithClassPath(classPath, mainClass);
+ } else {
+ System.out.println("Could not extract classpath or main class from the output.");
+ }
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String extractClassPathFromOutput(BufferedReader bufferedReader) throws IOException {
+ String line;
+ HashMap sepMap = new HashMap();
+ HashMap cpPatternMap = new HashMap();
+ HashMap cpEndPatternMap = new HashMap();
+
+ sepMap.put("Linux", "/");
+ sepMap.put("Windows", "\\");
+
+ cpPatternMap.put("Linux", "-classpath ");
+ cpPatternMap.put("Windows", "-classpath '");
+
+ cpEndPatternMap.put("Linux", " ");
+ cpEndPatternMap.put("Windows", "\'");
+
+ String classPath = null;
+ String platformName = System.getProperty("os.name");
+ if (platformName.contains("Windows")) {
+ platformName = "Windows";
+ } else {
+ // Mac and Linux have the same representations.
+ platformName = "Linux";
+ }
+ final String pattern = cpPatternMap.get(platformName);
+ while ((line = bufferedReader.readLine()) != null) {
+ int startIndex = line.indexOf(pattern);
+ if (startIndex > -1) {
+ startIndex += pattern.length();
+ int endIndex = line.indexOf(cpEndPatternMap.get(platformName).charAt(0), startIndex);
+ if (endIndex > startIndex) {
+ classPath = line.substring(startIndex, endIndex);
+ break;
+ }
+ }
+ }
+
+ System.out.println("Extracted ClassPath = " + classPath);
+ return classPath;
+ }
+
+ private void runJavaWithClassPath(String classPath, String mainClass) {
+ try {
+ ProcessBuilder pb = new ProcessBuilder("java", "-classpath", classPath, mainClass);
+ pb.inheritIO();
+ pb.start().waitFor();
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/JarRunner.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/JarRunner.java
new file mode 100644
index 000000000..c2e9d04af
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/JarRunner.java
@@ -0,0 +1,48 @@
+package com.edgechain.lib.flyfly.commands.run;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.edgechain.lib.flyfly.utils.FileTools;
+import com.edgechain.lib.flyfly.utils.ProjectSetup;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JarRunner {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ ProjectSetup projectSetup;
+ @Autowired
+ FileTools fileTools;
+
+ public void run(File jarFile) {
+ try {
+ log.info("Checking if glowroot agent exists");
+ if (!projectSetup.glowrootAgentExists()) {
+ log.info("Agent doesn't exist");
+ log.info("Adding glowroot agent");
+ projectSetup.addGlowrootAgent();
+ }
+ log.info("Runnng the jar");
+ String agentPath = projectSetup.getGlowrootAgentPath();
+ String jarPath = jarFile.getAbsolutePath();
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS)
+ command = new String[] {"cmd", "/c", "java -javaagent:" + agentPath + " -jar " + jarPath};
+ else
+ command = new String[] {"bash", "-c", "java -javaagent:" + agentPath + " -jar " + jarPath};
+
+ ProcessBuilder pb = new ProcessBuilder(command);
+ pb.inheritIO();
+ pb.start().waitFor();
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/ProjectRunner.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/ProjectRunner.java
new file mode 100644
index 000000000..e177880a1
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/ProjectRunner.java
@@ -0,0 +1,190 @@
+package com.edgechain.lib.flyfly.commands.run;
+
+import static java.nio.file.StandardWatchEventKinds.*;
+
+import com.edgechain.lib.flyfly.utils.ProjectSetup;
+import jakarta.annotation.PreDestroy;
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.zeroturnaround.exec.ProcessExecutor;
+
+@Component
+public class ProjectRunner {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+
+ @Autowired TestContainersStarter testContainersStarter;
+ @Autowired
+ ProjectSetup projectSetup;
+
+ Process runningProcess;
+ WatchService filesWatcher;
+ WatchService buildFileWatcher;
+ boolean allowInfrastructureServices;
+
+ public void run() {
+ try {
+ log.info("Configuring the project");
+ log.info("Checking if initscript exists");
+ if (!projectSetup.initscriptExists()) {
+ log.info("Initscript doesn't exist");
+ log.info("Adding flyfly.gradle to initscripts");
+ projectSetup.addInitscript();
+ }
+ projectSetup.addAutorouteJar();
+ allowInfrastructureServices = isDockerInstalled();
+ if (allowInfrastructureServices) checkAndConfigureServices();
+ log.debug("registering watcher for src files changes");
+ registerFilesWatcher();
+ log.debug("registering watcher for build file changes");
+ registerBuildFileWatcher();
+ log.info("Starting the project");
+ runTheProject();
+ loop();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ boolean isDockerInstalled() throws IOException, InterruptedException {
+ log.info("Checking if docker is installed to allow infrastructure services");
+ int exitCode;
+ try {
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS) command = new String[] {"cmd", "/c", "docker", "info"};
+ else command = new String[] {"docker", "info"};
+
+ exitCode = new ProcessExecutor().command(command).start().getProcess().waitFor();
+ } catch (Exception e) {
+ exitCode = -1;
+ }
+ if (exitCode != 0) {
+ log.warn("Couldn't find docker. Disabling infrastructure services.");
+ return false;
+ }
+ return true;
+ }
+
+ void runTheProject() throws IOException {
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS) command = new String[] {"cmd", "/c", "gradlew.bat", "bootRun"};
+ else command = new String[] {"./gradlew", "bootRun"};
+
+ runningProcess =
+ new ProcessExecutor().command(command).redirectOutput(System.out).start().getProcess();
+ }
+
+ void checkAndConfigureServices() throws IOException {
+ log.info("Checking if services are needed");
+// Set supportedDBGroupIds =
+// Set.of("mysql", "com.mysql", "org.postgresql", "org.mariadb.jdbc");
+ Set supportedDBGroupIds =
+ Set.of( "org.postgresql");
+ BufferedReader reader = new BufferedReader(new FileReader("build.gradle"));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (line.contains("dependencies")) {
+ while ((line = reader.readLine()) != null) {
+ int start = line.indexOf("\'");
+ int end = line.indexOf(":");
+ if (start < 0 || end < 0) continue;
+ String groupID = line.substring(start + 1, end);
+ if (supportedDBGroupIds.contains(groupID)) {
+ if (!testContainersStarter.isServiesNeeded()) break;
+ log.info("Found : " + groupID);
+ switch (groupID) {
+// case "mysql", "com.mysql" -> testContainersStarter.startMySQL();
+ case "org.postgresql" -> testContainersStarter.startPostgreSQL();
+// case "org.mariadb.jdbc" -> testContainersStarter.startMariaDB();
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ reader.close();
+ }
+
+ void registerBuildFileWatcher() throws IOException {
+ Path path = Paths.get("");
+ buildFileWatcher = FileSystems.getDefault().newWatchService();
+ path.register(buildFileWatcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+ }
+
+ public void loop() throws IOException, InterruptedException {
+ while (true) {
+ if (didFilesChange() && runningProcess.isAlive()) {
+ reloadTheProject();
+ }
+ if (didBuildFileChange()) {
+ handleBuildFileChange();
+ }
+ }
+ }
+
+ void registerFilesWatcher() throws IOException {
+ Path path = Paths.get("src");
+ filesWatcher = FileSystems.getDefault().newWatchService();
+ Files.walkFileTree(
+ path,
+ new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ dir.register(filesWatcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
+ void reloadTheProject() throws IOException, InterruptedException {
+ destroyRunningProcess();
+ runTheProject();
+ }
+
+ boolean didFilesChange() throws InterruptedException {
+ WatchKey key = filesWatcher.poll(500, TimeUnit.MILLISECONDS);
+ if (key == null) return false;
+ for (WatchEvent> event : key.pollEvents()) {}
+ key.reset();
+ if (!runningProcess.isAlive()) return false;
+ return true;
+ }
+
+ boolean didBuildFileChange() throws InterruptedException {
+ WatchKey key = buildFileWatcher.poll(500, TimeUnit.MILLISECONDS);
+ if (key == null) return false;
+ boolean found = false;
+ for (WatchEvent> event : key.pollEvents()) {
+ Path p = (Path) event.context();
+ if (p.endsWith("build.gradle")) found = true;
+ }
+ key.reset();
+ if (found) log.info("Detected build file change ...");
+ return found;
+ }
+
+ void handleBuildFileChange() throws IOException, InterruptedException {
+ destroyRunningProcess();
+ if (allowInfrastructureServices) checkAndConfigureServices();
+ runTheProject();
+ }
+
+ @PreDestroy
+ void destroyRunningProcess() throws InterruptedException, IOException {
+ if (runningProcess == null) return;
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Runtime.getRuntime().exec("cmd.exe /c taskkill /f /t /pid " + runningProcess.pid()).waitFor();
+ } else runningProcess.destroy();
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/RunCommand.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/RunCommand.java
new file mode 100644
index 000000000..afde3efff
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/RunCommand.java
@@ -0,0 +1,35 @@
+package com.edgechain.lib.flyfly.commands.run;
+
+import java.io.File;
+
+import com.edgechain.lib.flyfly.utils.ProjectTypeChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Parameters;
+
+@Component
+@Command(name = "run", description = "Run a JAR or Gradle Spring Boot Application. Ignore if your application is executed.")
+public class RunCommand implements Runnable {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ @Parameters(hidden = true)
+ File[] files;
+
+ @Autowired ProjectRunner projectRunner;
+ @Autowired ProjectTypeChecker projectTypeChecker;
+ @Autowired JarRunner jarRunner;
+
+ @Override
+ public void run() {
+ if (files != null && files.length > 0) jarRunner.run(files[0]);
+ else if (projectTypeChecker.isGradleProject()) projectRunner.run();
+ else {
+ log.error("Couldn't find build.gradle");
+ log.error("Please try again inside the project directory");
+ }
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/TestContainersStarter.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/TestContainersStarter.java
new file mode 100644
index 000000000..ad7c0080b
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/commands/run/TestContainersStarter.java
@@ -0,0 +1,155 @@
+package com.edgechain.lib.flyfly.commands.run;
+
+import jakarta.annotation.PreDestroy;
+import java.io.*;
+import java.nio.file.FileSystems;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.testcontainers.containers.PostgreSQLContainer;
+
+
+@Component
+public class TestContainersStarter {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ private static final String dbName = "test";
+ private static final String userName = "test";
+ private static final String password = "test";
+// private MySQLContainer> mysql;
+ private PostgreSQLContainer> postgre;
+// private MariaDBContainer> mariaDB;
+ private String flyflyTempTag = "#flyfly_temp_property";
+
+// public void startMySQL() throws IOException {
+// if (mysql != null && mysql.isRunning()) return;
+// log.info("Starting a temporary MySQL database.");
+// mysql =
+// new MySQLContainer<>(DockerImageName.parse("mysql:5.7"))
+// .withDatabaseName(dbName)
+// .withUsername(userName)
+// .withPassword(password);
+// mysql.addParameter("TC_MY_CNF", null);
+// mysql.start();
+// log.info("Database started.");
+// log.info("DB URL: " + mysql.getJdbcUrl());
+// log.info("DB Username: " + mysql.getUsername());
+// log.info("DB Password: " + mysql.getPassword());
+// addTempProperties(mysql.getJdbcUrl());
+// }
+
+ public void startPostgreSQL() throws IOException {
+ if (postgre != null && postgre.isRunning()) return;
+ log.info("Starting a temporary PostgreSQL database.");
+ postgre =
+ new PostgreSQLContainer<>("postgres:14.5")
+ .withDatabaseName(dbName)
+ .withUsername(userName)
+ .withPassword(password);
+ postgre.addParameter("TC_MY_CNF", null);
+ postgre.start();
+ log.info("Database started.");
+ log.info("DB URL: " + postgre.getJdbcUrl());
+ log.info("DB Username: " + postgre.getUsername());
+ log.info("DB Password: " + postgre.getPassword());
+ addTempProperties(postgre.getJdbcUrl());
+ }
+
+// public void startMariaDB() throws IOException {
+// if (postgre != null && postgre.isRunning()) return;
+// log.info("Starting a temporary MariaDB database.");
+// mariaDB =
+// new MariaDBContainer<>("mariadb:10.3.6")
+// .withDatabaseName(dbName)
+// .withUsername(userName)
+// .withPassword(password);
+// mariaDB.addParameter("TC_MY_CNF", null);
+// mariaDB.start();
+// log.info("Database started.");
+// log.info("DB URL: " + mariaDB.getJdbcUrl());
+// log.info("DB Username: " + mariaDB.getUsername());
+// log.info("DB Password: " + mariaDB.getPassword());
+// addTempProperties(mariaDB.getJdbcUrl());
+// }
+
+ public void addTempProperties(String url) throws IOException {
+ log.info("Appending temporary DB configuration to application.properties");
+ BufferedWriter writer = new BufferedWriter(new FileWriter(getPropertiesPath(), true));
+ writer.newLine();
+ writer.append(flyflyTempTag);
+ writer.newLine();
+ writer.append("spring.datasource.url=" + url);
+ writer.newLine();
+ writer.append(flyflyTempTag);
+ writer.newLine();
+ writer.append("spring.datasource.username=" + userName);
+ writer.newLine();
+ writer.append(flyflyTempTag);
+ writer.newLine();
+ writer.append("spring.datasource.password=" + password);
+ writer.flush();
+ writer.close();
+ }
+
+ public void removeTempProperties() throws IOException {
+ BufferedReader reader = new BufferedReader(new FileReader(getPropertiesPath()));
+ StringBuilder sb = new StringBuilder();
+ boolean tempNotFound = true;
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (line.contains(flyflyTempTag)) {
+ tempNotFound = false;
+ reader.readLine();
+ continue;
+ }
+ sb.append(line + "\n");
+ }
+ reader.close();
+ if (tempNotFound) return;
+
+ BufferedWriter writer = new BufferedWriter(new FileWriter(getPropertiesPath()));
+ writer.write(sb.toString());
+ writer.flush();
+ writer.close();
+ }
+
+ public boolean isServiesNeeded() throws IOException {
+ BufferedReader reader = new BufferedReader(new FileReader(getPropertiesPath()));
+ String line;
+ String datafield = "spring.datasource.url";
+ while ((line = reader.readLine()) != null) {
+ if (line.contains(datafield)) {
+ reader.close();
+ return false;
+ }
+ }
+ reader.close();
+ return true;
+ }
+
+ public String getPropertiesPath() {
+ String separator = FileSystems.getDefault().getSeparator();
+ return System.getProperty("user.dir")
+ + separator
+ + "src"
+ + separator
+ + "main"
+ + separator
+ + "resources"
+ + separator
+ + "application.properties";
+ }
+
+ @PreDestroy
+ public void destroy() {
+ try {
+ removeTempProperties();
+ } catch (IOException e) {
+ }
+// if (mysql != null && mysql.isRunning()) mysql.close();
+ if (postgre != null && postgre.isRunning()) postgre.close();
+// if (mariaDB != null && mariaDB.isRunning()) mariaDB.close();
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/FileTools.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/FileTools.java
new file mode 100644
index 000000000..046eeb69b
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/FileTools.java
@@ -0,0 +1,31 @@
+package com.edgechain.lib.flyfly.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import net.lingala.zip4j.ZipFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class FileTools {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ public void exportFileTo(String file, String dest) throws IOException {
+ log.debug("Exporting " + file + " To " + dest);
+ InputStream resource = FileTools.class.getClassLoader().getResourceAsStream(file);
+ Files.copy(resource, Path.of(dest));
+ log.debug("Exported successfully");
+ }
+
+ public void unzip(String zipFilePath, String destDir) throws IOException {
+ log.debug("Unzipping " + zipFilePath + " into " + destDir);
+ ZipFile zipFile = new ZipFile(zipFilePath);
+ zipFile.extractAll(destDir);
+ zipFile.close();
+ log.debug("Unzipped successfully");
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectSetup.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectSetup.java
new file mode 100644
index 000000000..d6b86789d
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectSetup.java
@@ -0,0 +1,74 @@
+package com.edgechain.lib.flyfly.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ProjectSetup {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired FileTools fileTools;
+
+ private String userHome = System.getProperty("user.home");
+ private String separator = FileSystems.getDefault().getSeparator();
+ private String initscriptDir =
+ userHome + separator + ".gradle" + separator + "init.d" + separator + "flyfly.gradle";
+ private String flyflyDir = System.getProperty("user.dir") + separator + ".flyfly";
+ private String formatScriptDir = flyflyDir + separator + "format.gradle";
+ private String autorouteDir = flyflyDir + separator + "autoroute.jar";
+ private String glowrootDir = flyflyDir + separator + "glowroot";
+
+ public boolean initscriptExists() {
+ log.debug("Checking if flyfly.gradle exists in " + initscriptDir);
+ return new File(initscriptDir).exists();
+ }
+
+ public void addInitscript() throws IOException {
+ File initDir = new File(userHome + separator + ".gradle" + separator + "init.d");
+ if (!initDir.exists()) initDir.mkdirs();
+ fileTools.exportFileTo("flyfly.gradle", initscriptDir);
+ }
+
+ public void addAutorouteJar() throws IOException {
+ File flyflyFolder = new File(flyflyDir);
+ if (!flyflyFolder.exists()) flyflyFolder.mkdirs();
+ File autorouteFile = new File(autorouteDir);
+ if (!autorouteFile.exists() || (autorouteFile.exists() && autorouteFile.delete()))
+ fileTools.exportFileTo("autoroute.jar", autorouteDir);
+ }
+
+ public boolean formatScriptExists() {
+ log.debug("Checking if format.gradle exists in " + formatScriptDir);
+ return new File(formatScriptDir).exists();
+ }
+
+ public void addFormatScript() throws IOException {
+ File flyflyFolder = new File(flyflyDir);
+ if (!flyflyFolder.exists()) flyflyFolder.mkdirs();
+ fileTools.exportFileTo("format.gradle", formatScriptDir);
+ }
+
+ public boolean glowrootAgentExists() {
+ log.debug("Checking if glowroot folder exists in " + glowrootDir);
+ return new File(glowrootDir).exists();
+ }
+
+ public void addGlowrootAgent() throws IOException {
+ File flyflyFolder = new File(flyflyDir);
+ if (!flyflyFolder.exists()) flyflyFolder.mkdirs();
+ String zipDir = flyflyDir + separator + "glowroot.zip";
+ fileTools.exportFileTo("glowroot.zip", zipDir);
+ fileTools.unzip(zipDir, flyflyDir);
+ new File(zipDir).delete();
+ }
+
+ public String getGlowrootAgentPath() {
+ return flyflyDir + separator + "glowroot" + separator + "glowroot.jar";
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectTypeChecker.java b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectTypeChecker.java
new file mode 100644
index 000000000..1fa9857bf
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/java/com/edgechain/lib/flyfly/utils/ProjectTypeChecker.java
@@ -0,0 +1,20 @@
+package com.edgechain.lib.flyfly.utils;
+
+import java.io.File;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ProjectTypeChecker {
+
+ public boolean isMavenProject() {
+ File dir = new File(System.getProperty("user.dir"));
+ for (File file : dir.listFiles()) if (file.getName().equals("pom.xml")) return true;
+ return false;
+ }
+
+ public boolean isGradleProject() {
+ File dir = new File(System.getProperty("user.dir"));
+ for (File file : dir.listFiles()) if (file.getName().equals("build.gradle")) return true;
+ return false;
+ }
+}
diff --git a/FlySpring/edgechain-app/src/main/resources/application.properties b/FlySpring/edgechain-app/src/main/resources/application.properties
index 81f3f10ac..3efd93515 100644
--- a/FlySpring/edgechain-app/src/main/resources/application.properties
+++ b/FlySpring/edgechain-app/src/main/resources/application.properties
@@ -1,8 +1,12 @@
spring.main.allow-bean-definition-overriding=true
+spring.banner.location=classpath:banner.txt
spring.mvc.async.request-timeout=1200000
spring.servlet.multipart.max-file-size=70MB
spring.servlet.multipart.max-request-size=100MB
spring.jackson.default-property-inclusion=NON_NULL
logging.level.org.apache.tika.parser.pdf=error
logging.level.org.apache.pdfbox=error
-logging.level.org.apache.fontbox.ttf.CmapSubtable=error
\ No newline at end of file
+logging.level.org.apache.fontbox.ttf.CmapSubtable=error
+spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
+spring.jpa.hibernate.ddl-auto=none
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
\ No newline at end of file
diff --git a/FlySpring/edgechain-app/src/main/resources/banner.txt b/FlySpring/edgechain-app/src/main/resources/banner.txt
new file mode 100644
index 000000000..e3580b9cc
--- /dev/null
+++ b/FlySpring/edgechain-app/src/main/resources/banner.txt
@@ -0,0 +1,6 @@
+ ______ __ ________ _
+ / ____/___/ /___ ____ / ____/ /_ ____ _(_)___
+ / __/ / __ / __ `/ _ \ / / / __ \/ __ `/ / __ \
+ / /___/ /_/ / /_/ / __/ / /___/ / / / /_/ / / / / /
+/_____/\__,_/\__, /\___/ \____/_/ /_/\__,_/_/_/ /_/
+ /____/
diff --git a/FlySpring/edgechain-app/src/main/resources/glowroot.zip b/FlySpring/edgechain-app/src/main/resources/glowroot.zip
new file mode 100644
index 000000000..00b2b7fc1
Binary files /dev/null and b/FlySpring/edgechain-app/src/main/resources/glowroot.zip differ
diff --git a/FlySpring/edgechain-app/src/test/java/com/edgechain/EdgeChainRunnerTest.java b/FlySpring/edgechain-app/src/test/java/com/edgechain/EdgeChainRunnerTest.java
deleted file mode 100644
index fe5aba9a6..000000000
--- a/FlySpring/edgechain-app/src/test/java/com/edgechain/EdgeChainRunnerTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.edgechain;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class EdgeChainRunnerTest {
-
- public static void main(String[] args) {
- SpringApplication.run(EdgeChainRunnerTest.class, args);
- }
-}