diff --git a/algofi-compile/Dockerfile.bak b/algofi-compile/Dockerfile.bak new file mode 100644 index 0000000..95fa0f8 --- /dev/null +++ b/algofi-compile/Dockerfile.bak @@ -0,0 +1,39 @@ +# 빌드 이미지로 OpenJDK 17 & Gradle을 지정 +FROM gradle:7.6.1-jdk17 AS build + +# 소스코드를 복사할 작업 디렉토리를 생성 +WORKDIR /app + +# 라이브러리 설치에 필요한 파일만 복사 +COPY build.gradle settings.gradle ./ + +# gradle dependencies를 실행하여 의존성 설치 +RUN gradle dependencies --no-daemon + +# 호스트 머신의 소스코드를 작업 디렉토리로 복사 +COPY . /app + +# Gradle 빌드를 실행하여 JAR 파일 생성 +RUN gradle clean build --no-daemon --stacktrace --info + +# 런타임 이미지로 Amazon Corretto JDK 17 지정 +FROM amazoncorretto:17 + +# 애플리케이션을 실행할 작업 디렉토리를 생성 +WORKDIR /app + +# 추가 패키지 설치 (컴파일 도구 포함) +RUN yum update -y && \ + yum install -y gcc gcc-c++ make \ + python3 python3-pip \ + nodejs npm && \ + yum clean all + +# 빌드 이미지에서 생성된 JAR 파일을 런타임 이미지로 복사 +COPY --from=build /app/build/libs/*.jar /app/algofi.jar + +# 9999 포트를 외부에 노출 +EXPOSE 9999 + +# 컨테이너 실행 시 자바 애플리케이션 실행 +ENTRYPOINT ["java", "-jar", "algofi.jar"] diff --git a/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CheckoutApiController.java b/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CheckoutApiController.java new file mode 100644 index 0000000..3a76d50 --- /dev/null +++ b/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CheckoutApiController.java @@ -0,0 +1,4 @@ +package gooroommoon.algofi_compile.api; + +public class CheckoutApiController { +} diff --git a/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CompileApiController.java b/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CompileApiController.java new file mode 100644 index 0000000..1444dec --- /dev/null +++ b/algofi-compile/src/main/java/gooroommoon/algofi_compile/api/CompileApiController.java @@ -0,0 +1,96 @@ +package gooroommoon.algofi_compile.api; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import gooroommoon.algofi_compile.dto.CodeExecutionRequest; +import org.springframework.http.HttpStatus; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@RestController +@RequestMapping("/api/compile") +public class CompileApiController { + @PostMapping + public ResponseEntity compile(@RequestBody CodeExecutionRequest request) { + try { + String result = runCode(request.getCode(), request.getLanguage()); + return ResponseEntity.ok(result); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error in code execution: " + e.getMessage()); + } + } + + private String runCode(String code, String language) throws IOException, InterruptedException { + String fileName = "temp"; + ProcessBuilder builder = new ProcessBuilder(); + + switch (language.toLowerCase()) { + case "c": + Path cFilePath = Paths.get("temp." + language.toLowerCase()); + Files.write(cFilePath, code.getBytes()); + + builder.command("sh", "-c", "gcc " + cFilePath.toString() + " -o temp && ./temp"); //linux 버전 + //builder.command("cmd.exe", "/c", "gcc " + cFilePath.toString() + " -o temp && temp"); //windows 버전 + break; + + case "java": + int classIndex = code.indexOf("public class "); + if (classIndex != -1) { + int startIndex = classIndex + "public class ".length(); + int endIndex = code.indexOf(" ", startIndex); + if (endIndex != -1) { + fileName = code.substring(startIndex, endIndex); + } + } + + Path javaFilePath = Paths.get(fileName + "." + language.toLowerCase()); + Files.write(javaFilePath, code.getBytes()); + + String className = javaFilePath.toString().replace(".java", ""); + //builder.command("cmd.exe", "/c", "javac " + javaFilePath.toString() + " && java " + className); //windows 버전 + builder.command("sh", "-c", "javac " + javaFilePath.toString() + " && java " + className); //linux 버전 + break; + + case "javascript": + Path jsFilePath = Paths.get("temp." + language.toLowerCase()); + Files.write(jsFilePath, code.getBytes()); + + //builder.command("cmd.exe", "/c", "node " + jsFilePath.toString()); //windows 버전 + builder.command("sh", "-c", "node " + jsFilePath.toString()); //linux 버전 + + break; + case "python": + Path pyFilePath = Paths.get("temp." + language.toLowerCase()); + Files.write(pyFilePath, code.getBytes()); + + //builder.command("cmd.exe", "/c", "python " + pyFilePath.toString()); //windows 버전 + builder.command("sh", "-c", "python " + pyFilePath.toString()); //linux 버전 + + break; + default: + throw new IllegalArgumentException("Unsupported language: " + language); + } + + builder.redirectErrorStream(true); + Process process = builder.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + StringBuilder output = new StringBuilder(); + while ((line = reader.readLine()) != null) { + output.append(line + "\n"); + } + + int exitCode = process.waitFor(); + if (exitCode != 0) { + throw new RuntimeException("Execution failed with exit code " + exitCode); + } + return output.toString(); + } +} \ No newline at end of file diff --git a/algofi-compile/src/main/java/gooroommoon/algofi_compile/dto/CodeExecutionRequest.java b/algofi-compile/src/main/java/gooroommoon/algofi_compile/dto/CodeExecutionRequest.java new file mode 100644 index 0000000..17fd84a --- /dev/null +++ b/algofi-compile/src/main/java/gooroommoon/algofi_compile/dto/CodeExecutionRequest.java @@ -0,0 +1,44 @@ +package gooroommoon.algofi_compile.dto; + +public class CodeExecutionRequest { + private String code; // 실행할 코드 + private String language; // 코드의 프로그래밍 언어 + + // 기본 생성자 + public CodeExecutionRequest() { + } + + // 매개변수가 있는 생성자 + public CodeExecutionRequest(String code, String language) { + this.code = code; + this.language = language; + } + + // code 필드의 getter + public String getCode() { + return code; + } + + // code 필드의 setter + public void setCode(String code) { + this.code = code; + } + + // language 필드의 getter + public String getLanguage() { + return language; + } + + // language 필드의 setter + public void setLanguage(String language) { + this.language = language; + } + + @Override + public String toString() { + return "CodeExecutionRequest{" + + "code='" + code + '\'' + + ", language='" + language + '\'' + + '}'; + } +} diff --git a/algofi-compile/src/test/java/gooroommoon/algofi_compile/api/CompileApiControllerTest.java b/algofi-compile/src/test/java/gooroommoon/algofi_compile/api/CompileApiControllerTest.java new file mode 100644 index 0000000..f2edb9f --- /dev/null +++ b/algofi-compile/src/test/java/gooroommoon/algofi_compile/api/CompileApiControllerTest.java @@ -0,0 +1,44 @@ +package gooroommoon.algofi_compile.api; + +import gooroommoon.algofi_compile.dto.CodeExecutionRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +class CompileApiControllerTest { + + @Autowired + private CompileApiController compileApiController; + + @Test + public void testPythonExecution() throws Exception { + String pythonCode = "print('Hello, Python')"; + ResponseEntity response = compileApiController.compile(new CodeExecutionRequest(pythonCode, "python")); + assertEquals("Hello, Python\n", response.getBody()); + } + + @Test + public void testJavaExecution() throws Exception { + String javaCode = "public class Main { public static void main(String[] args) { System.out.println(\"Hello, Java\"); } }"; + ResponseEntity response = compileApiController.compile(new CodeExecutionRequest(javaCode, "java")); + assertEquals("Hello, Java\n", response.getBody()); + } + + @Test + public void testCExecution() throws Exception { + String cCode = "#include \nint main() {\nprintf(\"Hello, C\\n\");\nreturn 0;\n}"; + ResponseEntity response = compileApiController.compile(new CodeExecutionRequest(cCode, "c")); + assertEquals("Hello, C\n", response.getBody()); + } + + @Test + public void testJavascriptExecution() throws Exception { + String javascriptCode = "console.log('Hello, JavaScript')"; + ResponseEntity response = compileApiController.compile(new CodeExecutionRequest(javascriptCode, "javascript")); + assertEquals("Hello, JavaScript\n", response.getBody()); + } +} \ No newline at end of file