jar 내부의 manifest 본문 읽어오기
java 언어로 프로젝트를 진행 중 manifest 내부에 정보를 저장하고 빌드 후 .jar 파일에서 정보를 읽어와야하는 경우가 발생하였습니다. 이에 대하여 해결한 방법을 공유하고자 글을 씁니다.
개발 환경
- open jdk 11
- vscode
- spring boot
- gradle
예시
예시로 gradle 환경에서 manifest에 어플리케이션 버전 정보를 저장하고 REST API와 커맨드 라인 명령어를 통하여 버전 정보를 읽어올 수 있는 코드를 작성해 보겠습니다.
현재 개발중인 또는 테스트를 위한 프로젝트가 생성되어있다고 가정하겠습니다.
1.gradle을 통한 manifest에 버전 정보 저장
build.gradle 을 IDE 또는 본인이 사용하시에 편리한 편집기로 열어서 아래와 같은 코드를 추가합니다.
저는 VSCODE를 이용하여 편집하였습니다.
bootJar {
archiveBaseName = 'manifest_control_example'
manifest {
attributes(
"Application-Version" : "1.0.0"
)
}
}
위 코드를 작성하면 gradle을 통한 빌드 시 manifest_control_example.jar 라는 이름의 .jar가 생성되고 .jar 내부의 META-INF/MANIFEST.MF 파일을 편집기로 열어보면 Application-Version: 1.0.0 이라는 텍스트가 입력된 것을 확인하실 수 있을 겁니다.
이와 같이 Application-Vesion 이외에 빌드 날짜, 개발 환경 정보, 숨겨진 연애편지(?)등 원하는 정보를 작성할 수 있습니다.
이제는 쓰는법을 알았으니 원래 목적인 읽는 법을 알아보겠습니다.
2. manifest 정보 읽어오기
프로젝트 내부에 속하는 클래스 중 어떠한 클래스에도 상관 없지만 저는 편의를 위하여
ManifestController.java 라는 이름의 클래스를 만들었고 해당 클래스 내부에서 manifest의 정보를 읽어오는 코드를 작성해보겠습니다.
public class ManifestController {
private Manifest manifest;
public ManifestController() throws MalformedURLException, IOException {
String className = ManifestController.class.getSimpleName() + ".class";
String classPath = ManifestController.class.getResource(className).toString();
if (!classPath.startsWith("jar:file:")) {
return;
}
URL url = new URL(classPath);
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
manifest = jarConnection.getManifest();
}
public String getApplicationVersion() {
if (manifest == null) {
return null;
}
return manifest.getMainAttributes().getValue("Application-Version");
}
}
위와 같은 코드를 통해서 manifest에서 원하는 정보를 읽어올 수 있습니다.
먼저 .jar 내부에 포함될 아무 클래스나 상관없지만 너무 쌩뚱맞은 클래스를 이용하면 가독성이 떨어지니 현재 클래스인 ManifestController 클래스의 경로를 얻어옵니다.
이때 주의할 점은 빌드 후 .jar 에 담겨있을 클래스의 경로와 IDE 디버깅 상에서 class의 경로는 다르기 때문에 디버깅 상에서는 정상적인 .jar의 경로를 얻을 수 없으며 빌드 후에도 if문을 통하여 경로의 시작점이 jar인지 다시 한번 확인합니다.
정상적으로 경로가 얻어졌다면 if문을 통과할 것이고 얻어온 classPath 정보는 URL 클래스의 생성 인수로 사용되어 URL 클래스 객체를 생성하게 됩니다. 이 URL클래스 객체로 부터 openConnection()이라는 함수를 통하여 URLConnection 객체를 얻을 수 있게되는데 JarURLConnection 클래스는 URLConnection 클래스를 상속받은 하위 클래스이기에 형변환(이때의 형변환은 다운캐스팅)이 이루어질 수 있습니다.
이 JarURLConnection 객체는 getManifest() 라는 함수를 지원하며 해당 함수를 통하여.jar의 Manifest 객체를 얻을 수 있습니다.
이 Manifest 객체를 필드에 저장해놓으면
ManifestController의 생성자를 통하여 객체를 생성한 어딘가에서 getApplicationVersion() 함수를 이용하면 Application-Version 정보를 얻어올 수 있게 됩니다.
3. 커맨드 라인(Command Line)을 통하여 Manifest 정보 확인하기
이제 이 manifest 객체를 활용해볼 차례입니다.
먼저 커맨드 라인(Command Line)을 통하여 정보를 확인해보겠습니다.
public class Application {
public static void main(String[] args) throws IOException {
if (args.length > 0) {
for (String arg : args) {
if (arg.equalsIgnoreCase("-v") || arg.equalsIgnoreCase("-version")) {
ManifestController manifestController = new MainfestController();
System.out.println("Application-Version : " + manifestController.getApplicationVersion();
return;
}
}
return;
}
SpringApplication.run(Application.class, args);
}
}
위와 같이 main() 함수에 코드를 추가할 경우
터미널 창에서 ./java -jar manifest_control_example.jar -v 또는 ./java -jar manifest_control_example.jar -version 이라는 명령줄을 통하여 manifest로부터 Application-Version 정보를 가져올 수 있게 됩니다.
4. REST API 를 통하여 Manifest 정보 확인하기
졸음이 쏟아져 글이 점점 짧아짐을 느끼고 차후에 추가할 예정입니다..
한번이라도 REST API를 구현해보신 분이라면 어렵지 않게 구현하실 수 있으실거라 생각합니다..!