반응형

SWT 애플리케이션의 개발 과정 중에서 특히, 기본적인 프로토타입을 완성한 이후에, 전개 시 발생될 수 있는 문제에 대하여 고려하여야 합니다. 전통적인 자바 애플리케이션과는 달리, SWT 애플리케이션은 애플리케이션이 작동하기 전에 OS 스팩의 라이브러리들이 로딩되어야 합니다. 이러한 라이브러리들을 지속적으로 전개 및 관리해야 한다는 것은 쉽지 않지만 Sun의 Java Web Start가 도움이 됩니다. SWT와 Java Web Start가 결합하면 클라이언트 측 자바 애플리케이션 구축하는 데에 훌륭한 툴이 됩니다.

SWT 개요

Standard Widget Toolkit (SWT)을 개발 커뮤니티로 도입하기가 여간 까다로운 것이 아니다. 그러한 근거로는 Sun은 Java Foundation Classes (JFC)로 클라이언트 측 애플리케이션 개발자들을 여러 해 동안 회유하고는 있지만, 많은 개발자들은 여러 가지 이유로 이 툴킷 사용을 피하고 있다. 많은 개발자와 아키텍트에게 있어서, 전통적인 데스크탑 애플리케이션처럼 작동하는 클라이언트 측 자바 애플리케이션을 개발하는 것은 아직도 꿈과 같은 일이다.

2001년 중반에, 이클립스 프로젝트가 갑자기 생겨나기 시작했다. 처음에, 이클립스 프로젝트는 자바용 유일한 오픈 소스 Integrated Development Environment (IDE)로 인식되었다. 하지만, 그의 프로젝트의 범위는 훨씬 더 광범위해 졌으며, SWT 툴킷을 탄생시켰다. JFC와 사촌격인 Abstract Window Toolkit (AWT)와 마찬가지로, SWT 툴킷은 개발자용 위젯을 제공한다. 하지만, SWT와 다른 툴킷들과의 주요한 차이점은 SWT가 OS GUI 위젯을 사용하는 방식이다. 이러한 방식은 자바 개발자들에게 크로스 플랫폼 API를 제공하여 원래의 데스크탑 애플리케이션인 것 같은 느낌을 주는 솔루션을 구현할 수 있도록 해준다.




위로


Java Web Start 개요

어떤 언어든, 올바른 툴이 없다면 데스크탑 애플리케이션의 전개와 관리는 개발자들에게 가장 큰 고민거리가 될 것이다. 지원 부서들 조차 새로운 버전의 소프트웨어가 릴리스 될 때 모든 워크스테이션을 업데이트 해야 한다는 생각에 사로잡혀 있으며, 배포 및 관리 요구 사항들을 완화시키기 위해서, 몇년 전 Sun Microsystems는 Java Web Start를 도입했다. 이 기술은 엔드 유저의 워크스테이션에서 자바 애플리케이션의 전개, 관리, 업그레이드를 단순화 한다.

애플리케이션을 시작하는 초기 툴로서 웹 브라우저를 사용하는 Java Web Start는 Sun의 Java Runtime Environment에 포함된 로컬에서 설치된 헬퍼 애플리케이션이다. Java Network Launching Protocol (JNLP) 파일에 액세스 할 때마다, 애플리케이션은 사용자 워크스테이션으로 자동 다운로드 되어 실행을 시작한다. 전체 프로세스는 엔드 유저와의 인터랙션에 대한 필요성이 줄어들었고, 애플리케이션 분산 과정도 단순화 되었다. (참고자료)




위로


파일 뷰어 애플리케이션

Java Web Start를 사용하여 SWT 애플리케이션을 전개하는 방법을 보기 전에, 우리가 전개할 애플리케이션에 대해 잠깐 보도록 하자. 이 글에 소개된 애플리케이션은 이클립스 프로젝트에서 제공하는 예제 애플리케이션이다. 그림 1에서 보듯, 이 애플리케이션은 크로스-플랫폼(cross platform) 파일 뷰어로서 사용자들이 하드 드라이브 상의 파일과 폴더를 볼 수 있도록 한다.


그림 1. Windows XP에서 실행되는 파일 뷰어
File Viewer

SWT와 Java Web Start의 크로스 플랫폼 기능을 설명하기 위해, 이 글의 예제 애플리케이션은 Microsoft Windows와 Red Hat Linux에서 실행되도록 패키징 되어 있다.




위로


환경 요구 사항

본 기사에서 기술한 코드는 하단부에 명기된 링크를 통하여 다운로드 할 수 있다. Java Web Start로 파일 뷰어 애플리케이션을 테스트 하려면, 다음과 같은 조건이 충족되어야 한다. (참고자료의 다운로드 링크 참조)

  • Microsoft Windows XP 또는 Red Hat Linux 8 OS
  • Java 2 SDK, Standard Edition 1.4 또는 이후 버전
  • Apache Ant 1.5.3 또는 이후 버전
  • Jakarta Tomcat 4.1.24 또는 이후 버전

Ant 빌드 스크립트를 크로스 플랫폼으로 만드는 것이 본 글의 목적이지만, 파일 뷰어 애플리케이션은 Microsoft Windows XP와 Red Hat Linux 8 OS에서만 테스트 및 확인되었다. 또한, Tomcat은 로컬 워크스테이션과 8080 포트에서 실행되는 것으로 간주한다. 예제 애플리케이션을 구현 및 설치, 실행해보자.




위로


파일 뷰어 애플리케이션 설치하기

파일 뷰어 애플리케이션을 설치하려면 다음 단계를 따른다.

  1. 참고자료 섹션에서 제공하는 링크를 통해 소스 코드 패키지를 다운로드 한다.
  2. fileviewer.zip 파일을 임시 디렉토리에서 압축을 푼다.



위로


보안과 코드 사인

AWT나 JFC와는 달리, SWT는 OS 본연의 윈도우 환경과 긴밀히 연관되어 있다. SWT는 시스템 라이브러리를 사용하여 플랫폼 독립 API와 기반 OS 간 통합을 관리한다. 기본적으로, Java Web Start에서 실행되는 애플리케이션은 제한된 샌드박스(sandbox)에서 실행된다. 이 환경은 워크스테이션의 파일 시스템, 시스템 라이브러리, 기타 리소스 같은 리소스로의 액세스를 제어한다. SWT는 시스템 라이브러리를 로딩하기 위해서 기본 샌드박스 밖에서 실행되어야 하므로, Java Web Start에 전개된 모든 JAR 파일들은 디지털 서명이 필요하다. 이 애플리케이션은 광범위한 사용자 베이스로 전개할 것은 아니므로 자체 서명 테스트 인증을 만들 것이다.

만일 여러분이 SWT 애플리케이션을 실행 환경에 설치하려면, Thawte 또는 VeriSign 같은 인증 기구에서 인증서를 받아두는 것이 좋다.




위로


자체 서명 인증서 만들기

자체 서명 테스트 인증서를 만들려면 다음과 같이 한다.

  1. 소스 코드의 압축을 풀었던 디렉토리에서 다음 명령어를 실행한다: keytool -genkey -keystore keystore -alias myself.

    패스워드, 이름, 위치를 포함한 새로운 키에 대한 상세를 요청하는 프롬프트가 뜬다. Ant 빌드 프로세스를 사용하려면, 패스워드를 "password"로 설정한다. 패스워드를 "password"로 하지 않으려면, build.xml 파일 내에서 "sign-jars"를 편집한다. 각 JAR 파일을 서명하는 실제 프로세스는 Ant 구현 동안에 완료된다.

  2. 키스토어(Keystore)가 올바르게 생성되었는지를 확인하려면 소스 코드 압축을 풀었던 디렉토리에 다음 명령을 실행한다: keytool -list-keystore keystore

    결과는 다음과 같다:

    Keystore type: jks
    Keystore provider: SUN
           
    Your keystore contains 1 entry
           
    myself, Jun 3, 2003, keyEntry,
    Certificate fingerprint (MD5):B8:C4:48:ED:68:E8:FE:47:83:78:F5:14:4E:28:5C:80




위로


파일 뷰어 애플리케이션 구현하기

파일 뷰어 애플리케이션을 구현하려면, 다음 단계를 따라간다.

  1. 환경을 삭제하려면, 소스 코드 압축을 풀었던 디렉토리에서 ant clean 명령을 실행한다.
  2. ant 명령을 실행하여 빌드 프로세스를 시작한다.

요구 사항에 부합하는 환경이 마련되고 올바르게 설정되었다면 다음과 같은 내용을 볼 수 있다.

Buildfile: build.xml

init:

compile-common:

compile-module:
     [echo] Compiling ...

package-common:

package-swtlib:

sign-jars:
     [echo] Signing JARS...
  [signjar] Signing Jar : D:\FileViewer\dist\swt-lib.jar
  [signjar] Signing Jar : D:\FileViewer\dist\fileviewer.jar
     [copy] Copying 1 file to D:\FileViewer\dist
  [signjar] Signing Jar : D:\FileViewer\dist\swt-win32.jar

package-web:
      [war] Building war: D:\FileViewer\dist\fileviewer.war

default:

BUILD SUCCESSFUL
Total time: 6 seconds




위로


파일 뷰어 애플리케이션 실행하기

Java Web Start를 사용하여 파일 뷰어 애플리케이션을 전개하기 전에, 애플리케이션을 로컬에서 실행해 보자. 애플리케이션을 시작하려면 소스 코드의 압축을 풀었던 디렉토리에서 ant run을 실행한다.

Ant 스크립트를 실행하면 파일 뷰어 애플리케이션이 나타난다. 그림 2는 Red Hat Linux 8에서 실행되는 애플리케이션 모습이다.


그림 2. Red Hat Linux 8에서 실행되는 파일 뷰어
File viewer on Red Hat 8



위로


파일 뷰어 애플리케이션 전개 및 테스트

애플리케이션을 Tomcat 4에 전개하려면 다음과 같이 한다.

  1. Tomcat 4에서 dist 디렉토리에서 webapps 디렉토리로 fileviewer.war 파일을 복사한다.
  2. 스크립트를 실행하여 Tomcat 4를 시작한다.
  3. 웹 브라우저에서 http://localhost:8080/fileviewer/index.html로 들어가서 "Launch Application" 링크를 클릭한다.

    링크를 클릭하고, 애플리케이션의 JAR 파일이 워크스테이션으로 다운로드 되는 동안 다음과 같은 이미지를 볼 수 있다.(그림 3)



    그림 3. 파일 뷰어
    File viewer

  4. 애플리케이션이 처음 다운로드 되면, 다음과 같은 대화 창이 나타난다. (그림 4)

    그림 4. 보안 경고
    Security warning

    "Start"를 클릭하여 파일 뷰어 애플리케이션을 시작한다.




위로


JNLP 파일 구현하기

Sun의 Java Web Start를 사용하여 SWT 애플리케이션을 구현, 배포, 전개하는 방법을 알아보았다. 이제는 JNLP 파일을 구현하는 방법에 대해 알아보자. Java Network Launching Protocol 스팩은 Java Community Process (JCP)에서 관리된다. 이 글의 목적은 이 기술을 사용하여 SWT 애플리케이션을 전개하는 방법을 설명하는 것이기 때문에 그 외 배경 설명은 생략하도록 하겠다. Java Web Start에 대한 자세한 내용은 Steve Kim의 기술자료 "Java Web Start"를 참조하라. (참고자료)

Listing 1은 SWT 애플리케이션의 JNLP 파일에서 사용되는 다양한 태그들이다.


Listing 1. index.jnlp 파일
				
1  <?xmlversion="1.0" encoding="utf-8"?>
2     <jnlp spec="1.0+"codebase="http://localhost:8080/fileviewer"href="index.jnlp">
3         <information>
4                 <title>File Viewer</title>
5                 <vendor>IBM developerWorks</vendor>
6                 <homepage href="index.html"/>
7                 <description>File Viewer</description>
8                 <description kind="short">FileViewer</description>
9         </information>
10        <security>
11                 <all-permissions/>
12         </security>
13         <resources>
14                 <j2se version="1.4"/>
15                 <jar href="fileviewer.jar"/>
16                 <nativelib href="swt-lib.jar"/>
17         </resources>
18         <resources os="Windows"> 
19                 <jar href="swt-win32.jar"/>
20         </resources>
21         <resources os="Linux"> 
22                 <jar href="swt-linux.jar"/>
23         </resources>
24         <application-descmain-class="org.eclipse.swt.examples.fileviewer.FileViewer"/>
25 </jnlp>

이 XML 파일에서 중요한 부분을 살펴보도록 하자.

  1. SWT 애플리케이션은 실행하는 동안 시스템 라이브러리를 로딩해야 하므로, 사용자의 워크스테이션으로 완전히 액세스 해야 한다. 라인 10에서 12번은 애플리케이션이 클라이언트의 환경에 액세스를 요청하는 방법을 나타낸다. Java Web Start가 액세스 허용을 받으려면, 모든 애플리케이션의 JAR 파일들은 디지털 서명이 되어야 한다.
  2. 라인 16번에서 보듯, nativelib 태그를 선언하여 Java Web Start에게 이 JAR 파일에 원래의 라이브러리들이 포함되어 있음을 알려주어야 한다. 예제 파일 뷰어 애플리케이션에서, 이 JAR 파일에는 Windows DLL과 리눅스용 SO 파일 시리즈가 포함된다.
  3. 라인 23번은 각 OS에 대한 SWT JAR를 로딩하는 부분이다. "resources" 태그를 사용하여 특정 OS와 아키텍처에서만 사용될 리소스들을 보호할 수 있다. os 애트리뷰트는 리소스 엘리먼트가 관여할 OS를 지정하며, 해당 값은 엔드 유저의 os.name 자바 시스템 프로퍼티에 기반한다. 이 예제에서는 사용되지 않지만, 자바 라이브러리로 액세스를 제한할 때 arch 애트리뷰트를 사용할 수 있다. arch 애트리뷰트는 엔드 유저의 os.arch 자바 시스템 속성에 기반한다.

JNLP 파일의 다양한 엘리먼트와 포맷에 대한 정보는 참고자료 섹션을 참조하라.




위로


요약

SWT 사용자 인터페이스 툴킷과 Java Web Start가 결합하면 상호 작용하는 클라이언트 측 자바 애플리케이션을 전개하는 훌륭한 툴이 된다. 예제 파일 뷰어 애플리케이션은 Java Web Start를 통해 분산될 독립형 SWT 애플리케이션을 구현하는데 사용할 수 있는 빌드 및 패키징 프레임웍을 제공한다.

기사의 원문보기





위로


다운로드 하십시오

이름 크기 다운로드 방식
os-jws/fileviewer.zip  FTP
다운로드 방식에 대한 정보


참고자료


<출처: http://www.ibm.com/developerworks/kr/library/os-jws/>

반응형
자바 웹 스타트(JWS)는 웹 기반으로 애플리케이션을 배포할 수 있지 않습니까? 그런데 사람들은 왜 CD-ROM으로 자바 웹 스타트(JWS) 애플리케이션을 배포하려고 할까요? 이유는 여러 가지입니다. 우선, 대규모 애플리케이션이라면 고속 광대역 회선으로도 설치 프로그램 전체를 다운로드하기가 만만치 않을 수 있습니다. 둘째로, 기업 보안 등의 이유로 인해 온라인 연결이 안 되는 데스크탑도 많고 또 인터넷에 액세스할 수 없는 시스템도 많습니다. 마지막으로, 그저 CD가 더 좋다는 사람들이 많기 때문입니다.

클라이언트 기업에서 광대역 회선이 거의 없는 지역을 비롯하여 전 세계에 자사의 애플리케이션을 배포해 달라고 요청합니다. 이 애플리케이션에는 수많은 제품에 대한 정보와 함께 상세한 도면과 다이어그램까지 들어 있습니다. 애플리케이션의 상당 부분은 이러한 정보로 구성되어 있으며 JVM을 포함한 전체 설치 용량은 40MB를 넘어섭니다. 또 이 회사에서는 무역 박람회 등에서도 홍보물과 함께 이 애플리케이션을 CD에 담아 배포하고 싶다고 합니다. 그러므로 CD 배포도 준비해야 합니다. 보통, CD 설치에는 여러 가지 상업적 설치 프로그램이나 오픈소스 설치 프로그램을 이용하게 됩니다. 그러나 자바 웹 스타트로 실행하게 되어 있는 애플리케이션은 보통의 설치 프로그램에서와 달리 특정 위치에 설치해야 하며 사용자가 재량을 발휘할 여지가 없습니다.

이 기사에서는 CD와 인터넷 양쪽 모두를 이용하는 애플리케이션 설치 단계에 대해 설명합니다. 설치 프로세스에 필요한 조건은 다음과 같습니다.

  1. 설치된 애플리케이션은 업데이트를 스스로 확인하고 JWS 캐시와 통합되어야 합니다.
  2. 기존 또는 최신 버전의 자바 없이도 설치 후 즉시 시스템에서 실행할 수 있어야 합니다.
  3. 설치된 애플리케이션에는 인터넷 연결이 필요 없습니다.
  4. 설치된 프로그램은 사용하기 쉬워야 하며 사용자 인터페이스는 간단해야 합니다.

애플리케이션 설치는 보통 일반적인 설치 프로그램을 사용하여 이루어집니다. 그러나 기존의 설치 프로세스에서는 효율성 제고를 위해 JWS를 인식하지 못하는 별도의 애플리케이션을 작성하는 경우가 많았습니다. 따라서 업데이트가 발표될 때마다 사용자는 새 버전을 다운로드하여 설치해야 했습니다. 이와 달리 JWS 애플리케이션은 업데이트된 구성요소만 다운로드하므로 프로세스의 효율성과 신뢰성이 훨씬 더 높습니다. 그러므로 이 기사에서는 JWS 애플리케이션 설치 프로그램에 대해서도 설명하고자 합니다.


JWS 프라이머

자바 웹 스타트가 있으면 JNLP 파일 링크를 통해 자바 애플리케이션을 시작할 수 있습니다. 이 JNLP 파일은 애플리케이션에 대한 진입점 또는 기본 메소드를 설명하는 한편 애플리케이션에서 사용할 리소스를 참조합니다.

JWS 애플리케이션을 시작하면 JVM이 필요한 리소스에 액세스하려고 시도하면서, 경우에 따라 리소스를 업데이트하고 파일을 캐시로 복사합니다. 그 뒤로 이 애플리케이션을 시작하면 JWS가 이 캐시부터 확인하므로 리소스 다운로드 단계를 건너뛸 수 있습니다. 클라이언트 시스템이 오프라인 상태이거나 서버에 연결할 수 없는 경우, JWS는 오프라인 모드로 애플리케이션을 실행합니다.

JWS 시작 파일(JNLP 파일)이 CD에 들어 있는 경우, JWS는 서버에 연결하여 새 파일을 다운로드하려고 시도합니다. 물론 클라이언트 시스템이 온라인 상태일 때 이렇게 하는 것은 CD를 이용한 파일 배포의 취지에 어긋나는 일입니다. 대신에 우리는 앞서 JWS가 애플리케이션을 로드한 것처럼 JWS 캐시를 업데이트할 방법을 찾아야 합니다.


JWS 캐시 업데이트

자바 5 버전의 JWS에는 잘 알려진 -import 옵션이 있습니다. 이것은 특정 위치의 JWS 애플리케이션을 캐시로 가져오는 옵션입니다.

이 위치에 있는 CD 이미지는 보통 웹 서버에 배치되는 것, 즉 JNLP 파일과 이 JNLP 파일에서 참조하는 리소스 및 .jar 파일 등의 사본에 불과합니다. 서블릿을 사용하여 JNLP를 서비스하는 경우, CD 이미지를 실행하려면 생성된 JNLP 파일의 완벽한 스냅샷이 필요합니다.

따라서 다음을 호출하여 JWS 캐시에 CD 이미지를 설치할 수 있습니다.

<JAVA_HOME>/jre/bin/javaws -codebase <CACHE_IMAGE> -import <CACHE_IMAGE>/<XXXX>.jnlp

여기서 <JAVA_HOME>은 새 JVM 또는 기존 JVM의 루트이고, <CACHE_IMAGE>은 CD에서 JWS 애플리케이션의 위치이며, <XXXX>는 애플리케이션 JNLP 파일의 이름입니다. 이 명령을 자동화하고 간단한 GUI로 래핑하는 방법은 나중에 설명하겠습니다.

캐시에 저장된 애플리케이션을 설치하는 동안 JWS는 애플리케이션 시작을 위한 단축키를 바탕 화면이나 메뉴에 설치할지 묻는 메시지를 표시합니다. JWS 설치가 완료된 후 JWS를 다시 호출하여 새로 설치한 애플리케이션을 시작할 수 있습니다.

<JAVA_HOME>/jre/bin/javaws -import <CACHE_IMAGE>/<XXXX>.jnlp

여기서 다시 한 번 CD를 사용합니다. 그러나 이번에는 JWS가 JNLP 파일에서 참조하는 설치 리소스를 사용하게 됩니다. 시스템이 인터넷에 연결되어 있을 때는 통상적인 방법으로 업데이트를 확인한 다음, 애플리케이션을 시작합니다. 네트워크 연결이 설정되지 않았다면 CD에 저장된 상태 그대로 애플리케이션이 시작됩니다.

다음 번에 이 애플리케이션을 시작하는 사용자는 메뉴 또는 바탕 화면의 단축키를 사용할 수 있으며 CD는 이제 필요 없습니다. 아니면 웹 페이지의 링크를 사용하여 애플리케이션을 시작할 수 있습니다. 이 링크는 동일한 URL/JNLP 파일 조합, 예를 들면 해당 웹 사이트에 있던 원래 버전을 가리키는 링크여야 합니다.


JVM 문제

지금까지 설명한 내용에는 허점이 하나 있습니다. 위의 명령을 실행하려면 JVM이 있어야 하는데, 드물기는 하지만 JVM이 설치되어 있지 않거나 시스템 경로에 기본값으로 설정되어 있지 않아서 별도의 조치를 통해 사용 가능한 JVM을 찾아야 하는 경우가 있습니다. 이와 함께 사용자가 CD를 넣으면 설치가 시작되고 그 과정에서 기존 JVM이 있는지 자동으로 확인해야 합니다. 따라서 JVM 확인 프로세스는 다음과 같이 이루어집니다.

  1. 설치 프로그램이 JVM을 확인합니다.
  2. 없으면 JVM을 설치합니다.
  3. 설치 프로그램이 시작되고 사용자 라이센스 정보가 표시됩니다.
  4. 대상 JVM(위 1과 다른 버전을 애플리케이션이 요구하는 경우, 해당 버전)을 설치합니다.
  5. JWS 캐시를 가져옵니다.
  6. JWS 애플리케이션을 시작합니다.

JWS -import 옵션을 사용하기 위한 최소 JVM 버전이 자바 5라는 사실 때문에 몇 가지 문제가 더 발생합니다. 다시 말해, JVM이 설치되어 있고 애플리케이션에 사용할 수 있는 상태이더라도 이 import 옵션을 지정하려면 그 이상의 최신 JVM이 필요하게 됩니다. 둘째, 가져오기 프로세스에는 시간이 약간 걸리는데 애플리케이션을 시작하려면 먼저 이 프로세스를 마쳐야 합니다. 이렇게 실행이 지연되면 일반적인 다른 설치 프로그램과 같은 성능을 얻기가 어려워집니다.

이러한 문제를 고려한 결과, 위의 단계를 자동으로 수행할 수 있는 맞춤 시작형 애플리케이션을 제작하기로 했습니다.


설치 프로그램 실행

설치 프로세스의 실제 과정은 대부분 JWS -import 명령으로 처리되므로, 이 시작 애플리케이션의 주된 임무는 적절한 명령으로 JVM을 찾아 시작한 뒤 사용자에게 작업의 진행 과정을 GUI로 알려주는 것입니다.


JVM 찾기

Windows에서는 시스템 레지스트리의 HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment 키 아래에서 JVM을 찾을 수 있습니다. 이 키는 값이 여러 개일 수 있으며, 따라서 시작 애플리케이션은 레지스트리 항목을 반복하여 점검하면서 사용 가능한 최신 버전의 JVM을 찾아냅니다.

다음 메소드는 최소 및 최대 버전 번호의 인수를 대입하여 JVM 경로를 찾으려고 시도합니다.


private String getInstalledPath(
 
int majorMin, int minorMin, int revMin,
 
int majorMax, int minorMax, int revMax )
 
{
   
String installedPath = null;
   
int latestVersion = 0;

   
String keyRoot =
         
"HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft" +
         
"\\Java Runtime Environment";
   
Vector results = getRegEntries( "\"" + keyRoot + "\" /s" );
   
int numEntries = results.size();
   
for ( int i = 0; i < numEntries; i++ ) {
   
String key = results.get( i++ ).toString();
   
int pos = key.indexOf( "Java Runtime Environment" );
   
if ( pos > 0 ) {
      pos
+= "Java Runtime Environment".length() + 1;
     
String version = key.substring( pos );
     
String parts[] = version.split( "[._]" );
     
int majorVersion, minorVersion, revision;
      majorVersion
= Integer.parseInt( parts[ 1 ] );
     
if ( parts.length > 3 )
        minorVersion
= Integer.parseInt( parts[ 2 ] );
     
else
        minorVersion
= 0;
     
     
if ( parts.length > 4 )
        revision
= Integer.parseInt( parts[ 3 ] );
     
else
        revision
= 0;
       
     
if ((( majorVersion == -1 ) ||
           
( majorVersion >= majorMin )) &&

         
(( majorVersion == -1 ) ||
           
( majorVersion <= majorMax ))) {
       
if ((( minorMin == -1 ) ||
             
( minorVersion >= minorMin )) &&
           
(( minorMax == -1 ) ||
             
( minorVersion <= minorMax ))) {
         
if ((( revMin == -1 ) ||
               
( revision >= revMin )) &&
             
(( revMax == -1 ) ||
               
( revision <= revMax ))) {
           
// Prefer the neweset acceptable version
           
int thisVersion = majorVersion * 10000 +
                minorVersion
* 100 + revision;
           
if ( thisVersion > latestVersion ) {
             
String value = null;
             
while ( i < numEntries ) {
                value
= results.get( i++ ).toString().trim();
               
if ( value.startsWith( "JavaHome" ))
                 
break;
             
}
             
              installedPath
= value.substring(
                value
.indexOf( "REG_SZ" ) +  6 ).trim();
              latestVersion
= thisVersion;
           
}
         
}
       
}
     
}
   
}
 
}

 
return installedPath;
}

위 메소드의 키는 레지스트리 항목을 찾기 위한 키입니다. 레지스트리 값을 찾아주는 API는 여러 가지 있지만, 이 상황에서 가장 실용적인 것은 간단한 명령행 REG QUERY <key>입니다. 여기서 <key>는 쿼리할 레지스트리 경로입니다. 다음 메소드는 명령을 실행한 다음, 출력된 스트림 항목을 읽어 이를 Vector로 반환합니다.


private Vector getRegEntries( String key )
{
 
Vector results = new Vector();

 
try {
   
Process proc = Runtime.getRuntime().exec( "REG QUERY " +
      key
);
   
InputStream is = proc.getInputStream();
   
InputStreamReader isr = new InputStreamReader(is);


   
BufferedReader br = new BufferedReader(isr);
   
String result = "";
   
String line;

   
while (( line = br.readLine()) != null ) {
      line
= line.trim();
      results
.add( line );
   
}

   
return results;
 
}
 
catch ( Exception ex ) {
    message
( language.getString("6") + ex.getMessage() );
    ex
.printStackTrace();
 
}

 
return null;
}

JVM 설치

적당한 JVM을 찾을 수 없으면 CD에서 설치하면 됩니다. 단, 그 위치를 알고 있어야 합니다. 시작 프로그램은 properties 파일을 사용하여 필요한 여러 가지 리소스를 파악한 다음, 이 메커니즘을 통해 JVM 설치 패키지로 보낼 수 있습니다. 여기서도 마찬가지로, JVM 설치를 시작하려면 올바른 명령을 실행할 수 있어야 합니다. 그러나 이번에는 프로세스의 실행 시간이 비교적 길기 때문에 완료될 때까지 조금 기다려야 합니다. 실행(exec)된 프로세스의 waitFor 메소드는 완료될 때까지 스레드를 대기시키는 한편 UI 스레드의 차단을 방지하기 위해 이를 SwingWorker 안에 중첩시킵니다.


private void installJre()
{
 
try {
   
final String javaInstall = (String)props.get(
       
"jre_installer" );
    status
.setText( language.getString("3") );

   
SwingWorker worker = new SwingWorker()
   
{
     
public Object construct()
     
{
       
try {
         
Process process = Runtime.getRuntime().exec(
            workingDir
+ File.separatorChar +
            javaInstall
);
          process
.waitFor();
          exitValue
= new Integer( process.exitValue());
       
}
       
catch ( Exception ex ) {
          exitValue
= new Integer( -1 );
          ex
.printStackTrace();
       
}

       
return exitValue;
     
}

     
public void finished()
     
{
       
int ev = exitValue.intValue();
       
if ( exitValue != 0 ) {
          status
.setText( language.getString("Error:_") +
            exitValue
);
          message
( language.getString("4") );
       
}
       
else {
          installedJrePath
= getInstalledPath( 5, -1, -1,
                                               
5, -1, -1 );
          doInstall
( installedJrePath );
       
}
        status
.setText( "" );
     
}
   
};
    worker
.start();
 
}
 
catch ( Exception ex ) {
    status
.setText( language.getString( "5" ));
    ex
.printStackTrace();
 
}
}

JWS 시작 후 기다리기

JVM을 찾았으면 적절한 명령으로 이를 시작할 수 있습니다. JWS를 호출할 때, 첫 번째 가져오기 호출은 복사 및 완료하는 데 상당한 시간이 걸릴 수 있으므로 위와 같이 waitFor 메소드를 다시 사용합니다. 그러나 두 번째 호출부터는 애플리케이션을 시작하기만 하면 자동으로 처리됩니다. 일단 애플리케이션이 시작되면 시작 애플리케이션은 임무를 다한 것이므로 종료됩니다.


private void launchWebStart( String javaWSPath,
                             
String jnlpPath,
                             
String userDir )
{
 
try {
   
String webStartCommand = "\"" + javaWSPath + "\"" + " -wait
      -codebase file:///"
+ userDir + "\\"+ appDirectory +
     
" -import " + jnlpPath;
   
Process process = Runtime.getRuntime().exec(
      webStartCommand
);
    process
.waitFor();
   
int exitValue = process.exitValue();
   
if ( exitValue != 0 )
      status
.setText( language.getString("7") );
   
else
      status
.setText( language.getString("8") );


   
int rc = JOptionPane.showConfirmDialog( null,
      language
.getString("9"),
      language
.getString("10"),
     
JOptionPane.YES_NO_OPTION );
   
if ( rc == JOptionPane.YES_OPTION )
     
Runtime.getRuntime().exec( javaWSPath + " -offline " +
        jnlpPath
);

    status
.setText( language.getString("11") );
   
SwingWorker worker = new SwingWorker()
   
{
     
public Object construct()
     
{
       
try {
         
Thread.currentThread().sleep( 3000L );
       
}
       
catch ( Exception ex ) {
       
}

       
return null;
     
}

     
public void finished()
     
{
       
System.exit( 0 );
     
}
   
};
    worker
.start();
 
}
 
catch ( Exception ex ) {
    status
.setText( language.getString("12") );
    ex
.printStackTrace();
 
}
}


패키지 작성

설치를 위한 메커니즘은 모두 처리했습니다. 이제 시작 프로그램은 간단한 UI(아래 그림 1 참조)를 사용하여 사용자에게 진행 상황을 알려야 합니다.

사용자 삽입 이미지
그림 1. 설치 프로그램 시작 페이지(큰 그림으로 보려면 이미지 클릭)

UI는 현지화되어 있으며 로고, 애플리케이션 위치, JVM 버전 등을 config.properties 파일에서 구성할 수 있습니다. 소스를 포함한 전체 애플리케이션은 Aria project에서 오픈소스 라이센스로 구할 수 있습니다.

시작 애플리케이션을 제작하고 테스트까지 마친 뒤에는 완벽한 CD 설치 이미지를 작성하는 마지막 단계 하나만 남습니다. 그것이 바로 CD를 넣었을 때 설치를 시작하는 autorun 기능입니다. Windows용 autorun.inf 파일을 작성하는 방법에 대한 자세한 내용은 위키피디아의 Autorun 항목을 참조하십시오. 그러나 이 기능에는 원시 실행 파일이 필요합니다. 이러한 실행 파일을 작성하려면 Launch4J 래퍼를 사용하면 됩니다. Launch4J의 샘플 구성 파일은 다운로드한 소스에 포함되어 있습니다. Launch4J를 실행하면 해당 애플리케이션의 .exe 파일이 작성됩니다. 위에서 설명한 시작 애플리케이션은 자바 애플리케이션이고 사용자 시스템에는 JVM이 없을 수도 있으므로 여기서도 JVM을 래퍼와 함께 번들로 묶어야 합니다.

이렇게 .exe 파일을 작성한 다음, autorun.inf 파일을 작성하여 CD 이미지에 추가하면 됩니다.


[autorun]
open
=XXXX.exe
icon
=xxxx.ico
action
=Open XXXX
label
=My Application


플랫폼 간 문제

위에서 설명한 애플리케이션 시작 프로그램은 Windows에만 있는 몇 가지 기능을 사용하며, 따라서 Windows에서만 실행됩니다. 그러나 이 기사에서 설명한 방법은 여러 플랫폼에서 응용할 수 있는 방법이며, 다른 플랫폼을 사용하는 경우에는 기본 시작 프로그램을 사용할 수 있는지 여부만 확인하면 됩니다. 예를 들어, IzPack에는 몇 가지 플랫폼용의 시작 프로그램이 포함되어 있습니다. 또한 Mac OS X 처럼 문제의 플랫폼에 JVM이 있는 것이 확실하면 JVM에서 직접 시작 애플리케이션을 실행할 수 있으므로 기본 시작 프로그램은 필요가 없습니다.


결론

자바 웹 스타트와 Launch4J를 조합하여 CD를 작성하면 무역 박람회의 관람객 등에게 이 CD를 배포하여 빠르고 쉽게 애플리케이션을 설치하도록 할 수 있습니다. 사용자는 자바 웹 스타트의 전체 업데이트 기능을 사용하여 손쉽게 업데이트를 구할 수도 있고, 인터넷 연결이 불가능한 경우에는 애플리케이션 자체를 이용할 수도 있으므로 양쪽의 장점만 취하는 방법입니다.


참고 자료

Luan O'Carroll은 소프트웨어 개발자로서 Aria 프로젝트에 선임 연구원으로 참여하고 있습니다.


이 글의 영문 원본은
Distributing a Java Web Start Application via CD-ROM
에서 보실 수 있습니다.

크리에이티브 커먼즈 라이센스
Creative Commons License

<출처: http://www.sdnkorea.com/blog/638 >

+ Recent posts