feat: initial commit - cybercore signer desktop agent
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>br.com.cybercore.signer</groupId>
|
||||
<artifactId>cybercore-signer-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>cybercore-app</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>CyberCore Signer :: Application</name>
|
||||
<description>Módulo executável desktop, ciclo de vida da aplicação, shutdown hooks e empacotamento nativo.</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>br.com.cybercore.signer</groupId>
|
||||
<artifactId>cybercore-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>br.com.cybercore.signer</groupId>
|
||||
<artifactId>cybercore-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaFX Neutro -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaFX Nativos Windows (para execução direta em ambiente Windows) -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-base</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaFX Nativos Linux (para execução direta em ambiente Linux) -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-base</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Testes de Arquitetura -->
|
||||
<dependency>
|
||||
<groupId>com.tngtech.archunit</groupId>
|
||||
<artifactId>archunit-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>br.com.cybercore.signer.app.CyberCoreSignerApplication</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Geração de Fat JAR executável autocontido -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>cybercore-signer</finalName>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>br.com.cybercore.signer.app.CyberCoreSignerApplication</mainClass>
|
||||
<manifestEntries>
|
||||
<Implementation-Title>CyberCore Signer</Implementation-Title>
|
||||
<Implementation-Version>${project.version}</Implementation-Version>
|
||||
<Implementation-Vendor>CyberCore</Implementation-Vendor>
|
||||
</manifestEntries>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>module-info.class</exclude>
|
||||
<exclude>META-INF/versions/**/module-info.class</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
package br.com.cybercore.signer.app;
|
||||
|
||||
import br.com.cybercore.signer.core.diagnostics.DiagnosticReport;
|
||||
import br.com.cybercore.signer.core.diagnostics.DiagnosticService;
|
||||
import br.com.cybercore.signer.core.crypto.SigningService;
|
||||
import br.com.cybercore.signer.core.protocol.CcspServer;
|
||||
import br.com.cybercore.signer.core.provider.CertificateManager;
|
||||
import br.com.cybercore.signer.ui.CyberCoreDesktopApplication;
|
||||
import javafx.application.Application;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
/**
|
||||
* Ponto de entrada (Main Class) e bootstrap do agente CyberCore Signer.
|
||||
*/
|
||||
public class CyberCoreSignerApplication {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CyberCoreSignerApplication.class);
|
||||
|
||||
private static boolean developmentMode = false;
|
||||
private static boolean headlessMode = false;
|
||||
private static boolean noWaitMode = false;
|
||||
private static volatile CcspServer runningServer = null;
|
||||
|
||||
public static CcspServer getRunningServer() {
|
||||
return runningServer;
|
||||
}
|
||||
|
||||
public static void stopServer() {
|
||||
if (runningServer != null) {
|
||||
runningServer.stop();
|
||||
runningServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
parseArguments(args);
|
||||
printBanner();
|
||||
|
||||
logger.info("Inicializando CyberCore Signer v0.1.0...");
|
||||
if (developmentMode) {
|
||||
logger.warn("=========================================================");
|
||||
logger.warn(" MODO DE DESENVOLVIMENTO ATIVADO (--dev)");
|
||||
logger.warn(" Logs detalhados ativos. Operação com certificados reais.");
|
||||
logger.warn("=========================================================");
|
||||
}
|
||||
|
||||
DiagnosticService diagnosticService = new DiagnosticService();
|
||||
DiagnosticReport report = diagnosticService.runDiagnostic();
|
||||
logger.info("Ambiente verificado: OS={} {} ({}), Java={} ({})",
|
||||
report.osName(), report.osVersion(), report.osArch(),
|
||||
report.javaVersion(), report.javaVendor());
|
||||
|
||||
if (!report.cryptoEngineOk()) {
|
||||
logger.error("ALERTA CRÍTICO: Engine criptográfica JCA/JCE não está totalmente operacional!");
|
||||
}
|
||||
|
||||
// Se o ambiente tiver suporte gráfico e não for headless forçado, abre a interface JavaFX
|
||||
boolean isHeadless = headlessMode || GraphicsEnvironment.isHeadless();
|
||||
|
||||
if (isHeadless) {
|
||||
logger.info("Executando em modo console / headless (sem interface gráfica).");
|
||||
startHeadlessServer();
|
||||
} else {
|
||||
try {
|
||||
logger.info("Iniciando interface gráfica desktop...");
|
||||
CyberCoreDesktopApplication.setDevelopmentMode(developmentMode);
|
||||
Application.launch(CyberCoreDesktopApplication.class, args);
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Não foi possível inicializar ambiente gráfico ({}). Continuando em modo console.", t.getMessage());
|
||||
startHeadlessServer();
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("CyberCore Signer finalizado.");
|
||||
}
|
||||
|
||||
private static void startHeadlessServer() {
|
||||
try {
|
||||
CertificateManager certManager = CertificateManager.createDefault();
|
||||
if (developmentMode) {
|
||||
logger.info("Modo de desenvolvimento ativo (com certificados reais do sistema).");
|
||||
}
|
||||
SigningService signingService = new SigningService(certManager);
|
||||
runningServer = new CcspServer(certManager, signingService, null);
|
||||
runningServer.start();
|
||||
logger.info("Servidor local CCSP/1 pronto em http://127.0.0.1:{}", runningServer.getPort());
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
logger.info("Encerrando servidor local CCSP/1...");
|
||||
stopServer();
|
||||
}));
|
||||
|
||||
// Mantém processo vivo para atender requisições web, a menos que em modo no-wait
|
||||
if (!noWaitMode) {
|
||||
Thread.currentThread().join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
logger.error("Falha ao inicializar servidor local CCSP/1 no modo console: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseArguments(String[] args) {
|
||||
if (args != null) {
|
||||
for (String arg : args) {
|
||||
if ("--dev".equalsIgnoreCase(arg) || "-dev".equalsIgnoreCase(arg)) {
|
||||
developmentMode = true;
|
||||
} else if ("--headless".equalsIgnoreCase(arg) || "-headless".equalsIgnoreCase(arg)
|
||||
|| "--cli".equalsIgnoreCase(arg)) {
|
||||
headlessMode = true;
|
||||
} else if ("--no-wait".equalsIgnoreCase(arg) || "-no-wait".equalsIgnoreCase(arg)
|
||||
|| "--test".equalsIgnoreCase(arg)) {
|
||||
noWaitMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDevelopmentMode() {
|
||||
return developmentMode;
|
||||
}
|
||||
|
||||
public static boolean isHeadlessMode() {
|
||||
return headlessMode;
|
||||
}
|
||||
|
||||
private static void printBanner() {
|
||||
System.out.println("""
|
||||
============================================================
|
||||
____ _ ____
|
||||
/ ___| _ _ __| | ___ _ __ / ___|___ _ __ ___
|
||||
| | | | | |/ _` | / _ \\| '__| | | / _ \\ | '__|/ _ \\
|
||||
| |___ | |_| | (_| || __/| | | |__| (_) || | | __/
|
||||
\\____| \\__, |\\__,_| \\___||_| \\____\\___/ |_| \\___|
|
||||
|___/
|
||||
SIGNER AGENT v0.1.0
|
||||
============================================================
|
||||
""");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
|
||||
<logger name="br.com.cybercore.signer" level="DEBUG" />
|
||||
</configuration>
|
||||
@@ -0,0 +1,37 @@
|
||||
package br.com.cybercore.signer.app;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
|
||||
|
||||
class ArchitectureTest {
|
||||
|
||||
private final JavaClasses importedClasses = new ClassFileImporter()
|
||||
.importPackages("br.com.cybercore.signer");
|
||||
|
||||
@Test
|
||||
@DisplayName("O módulo Core não deve depender de classes dos pacotes UI ou App")
|
||||
void coreShouldNotDependOnUiOrApp() {
|
||||
ArchRule rule = noClasses()
|
||||
.that().resideInAPackage("br.com.cybercore.signer.core..")
|
||||
.should().dependOnClassesThat()
|
||||
.resideInAnyPackage("br.com.cybercore.signer.ui..", "br.com.cybercore.signer.app..");
|
||||
|
||||
rule.check(importedClasses);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("O módulo Core não deve conter dependências de bibliotecas JavaFX")
|
||||
void coreShouldNotDependOnJavaFx() {
|
||||
ArchRule rule = noClasses()
|
||||
.that().resideInAPackage("br.com.cybercore.signer.core..")
|
||||
.should().dependOnClassesThat()
|
||||
.resideInAPackage("javafx..");
|
||||
|
||||
rule.check(importedClasses);
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package br.com.cybercore.signer.app;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
class CyberCoreSignerApplicationTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Deve inicializar a aplicação com argumentos sem erros")
|
||||
void shouldBootstrapWithoutErrors() {
|
||||
try {
|
||||
assertThatCode(() -> CyberCoreSignerApplication.main(new String[]{"--dev", "--headless", "--no-wait"}))
|
||||
.doesNotThrowAnyException();
|
||||
} finally {
|
||||
CyberCoreSignerApplication.stopServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user