반응형

레지스트리는 운영체제와 프로그램에서 필요한 정보를 담고 있는 데이터베이스와 비슷하다고 할 수 있다. 일반적인 윈도우 프로그램들은 레지스트리에 접근 할 수 있지만 자바 프로그램에서는 접근 할 수 없었다. 그 이유는 "자바의 철학"에 위배 되기 때문일 것이다. 자바 프로그램은 모든 운영체제에서 실행 가능 해야 하는데 '윈도우에만 존재하는 레지스트리'라는 것을 지원하지 않는 것은 당연한 일이었다. 게다가 레지스트리는 잘못 건드리면 윈도우 자체가 폭탄처럼 변할 수 도 있기 때문에 상당히 조심스러울 수 밖에 없다.

하지만 JDK 1.4 버전부터는 일부 제한적으로 레지스트리에 접근 할 수 있도록 그 기능이 추가되었다. 보통 자바 프로그램에서는 프로그램 실행에 필요한 정보들을 파일로 저장해 두었다가 프로그램이 종료된 후 다시 실행하더라도 필요한 정보를 얻도록 하는 방법을 사용했다. 이때 파일을 사용하게 되면 이런 저런 이유로 코딩도 복잡하고 귀찮기 짝이 없다. 특별히 복잡한 정보도 아닌데 여러 모로 프로그래머가 고생을 하는 것이다. 바로 이런 경우에 레지스트리를 사용하면 간단히 해결된다. 아마도 많은 자바 개발자들의 요구 사항으로 인하여 JDK 1.4부터 추가 된 것이 아닌가 싶다.

그렇다면 과연 자바 프로그램에서 레지스트리를 어떻게 사용할 것인가? 아무리 좋은 기능이 있어도 그 기능을 적절한 곳에 사용하지 못한다면 소용이 없게 된다. 레지스트리에 스트링 값을 입력하고 읽어오는 간단한 예제를 하나 만들어 보도록 하자. (참고로 예제 작성과 실행은 윈도우 XP에서 이루어졌다. 윈도우 계열 운영체제에서는 대부분 작동하겠지만 윈도우를 제외한 다른 운영체제에서는 예측 할 수 없음을 밝혀두는 바이다.)

레지스트리를 이용한 사용자 인증 프로그램

우리가 주로 사용하는 윈도우 운영체제에서는 사용자 계정을 제공한다. 따라서 인증된 사용자가 아니면 사용할 수 없다. 우리가 작성할 예제는 이와 비슷하지만 훨씬 간단한 프로그램이다. 프로그램이 제공하게 될 간단한 기능은 다음과 같다.
프로그램을 처음 사용하는 경우, 이름을 입력 받아 레지스트리에 등록한다.
사용자로부터 이름을 입력 받아서 등록된 이름과 같다면 원하는 작업을 계속 수행한다.
등록된 이름이 아닌 경우라면 그냥 종료된다.

프로그램에 대한 설명은 따로 필요 없이 주석을 참고하면 된다. 그리고 컴파일이나 실행에 대해서 잘 모른다면 다른 자바 기초 서적을 참고하기 바란다.

소스 코드는 다음과 같다.

import java.util.prefs.*;
import java.io.*;

public class RegistryTest {

// 키와 값을 출력한다.
public static void printKeyValue(String key, String value) {
System.out.println("Key = [" + key + "] , Value = [" + value + "]");
}

// 해당 노드에 키를 포함하고 있는지 검사한다.
public static boolean contains(Preferences node, String key) {
return node.get(key, null) != null;
}

// 키보드로부터 이름을 입력받는다.
public static String readName() {
System.out.println("Input your name.");
String value = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(isr);
value = in.readLine();
} catch (IOException e) {
// 예외 처리...
}
return value;
}

public static void main(String args[]) throws BackingStoreException {
Preferences userRootPrefs = Preferences.userRoot();

String key = "name"; // 등록할 키 이름
String value = "";
String newName = null;
if (contains(userRootPrefs, key)) { // 이미 키가 존재한다.
System.out.println("Key already exists !");
value = userRootPrefs.get(key, "");
newName = readName(); // 키보드로부터 입력 받은 이름
if (newName.equals(value)) {
// 입력된 이름과 레지스트리에 등록된 이름 같다.
printKeyValue(key, value);
// 결과 출력 후, 다른 원하는 작업 수행...
}
else {
// 이름이 다르다, 당신은 누구얏 ?
System.out.println("Invalid user name !");
}
}
else { // 키가 없으므로 처음 레지스트리에 등록
value = readName();
userRootPrefs.put(key, value);
printKeyValue(key, value);
}
}
}

<출처:ibm.com/developerworks/kr>

반응형
'자바 프로그래머'라면 한번쯤 고민하게 되는 부분이 있다. 그 중 하나가 자바 API가 지원하지 못하는 부분에 대한 것이다. 예를 들어 자바 API로는 네트워크 인터페이스 카드(NIC, 흔히 랜 카드라고 부른다)의 맥 어드레스(MAC Address)를 알아 낼 방법이 없다. 결국 JNI(Java Native Interface)를 사용하거나 다른 꽁수(?)를 찾아내곤 한다. 본인이 생각하기에는 두 방법 모두 시원스런 방법은 아니라서 상당히 거시기한 느낌이다. JNI를 사용하자니 C/C++ 코드를 사용하여 플랫폼에 제한적이 되어버리고… 꽁수를 사용하자니 안 먹히는 경우가 너무 많고…

어쨌거나 다른 해결 방법이 없다면 둘 중 하나를 사용해야 한다. 두 가지 중에서 본인이 많이 사용하는 방법은 꽁수를 사용하는 방법이다. 여기서 말하는 꽁수란 원하는 결과를 얻을 수 있는 외부 프로세스를 실행시키고 그 결과를 받아내어 필요한 부분만 얻어내는 방법을 사용하는 것이다. 이번 기사에서는 윈도우 XP 운영체제의 시스템 비밀스런(?) 정보를 얻어내는 자바 프로그램을 만들어 보도록 하자.

※ 주의: 본 소스의 모든 내용은 윈도우 XP 프로페셔널에서만 동작한다. 윈도우 XP 홈에디션에는 시스템 정보를 얻어내는 프로그램(systeminfo.exe)이 지원되지 않는다.

일단 화면에 도스창을 하나 띄워보자. 그런 후, "systeminfo"라고 입력하면 자신이 사용하는 윈도우 시스템에 대한 여러 정보가 나타난다. 윈도우 XP 프로페셔널에 이런 프로그램이 있다는 사실은 본인도 이 프로그램을 작성하면서 처음 알게 된 것이다. 자세한 세부 사항은 "systeminfo /?"라고 입력하여 도움말을 참고하도록 하자.

화면에 보이는 결과를 살펴보면 의외로 많은 사실들을 알 수 있다. 운영체제의 자세한 버전이나 사용자 정보, 실제 메모리 정보, 운영체제에 적용된 패치 등등… 이제부터는 이 정보들을 이용하여 자신이 원하는 몇 가지만을 보여주는 간단한 프로그램을 만들어보자.

이 프로그램의 핵심은 자바 프로그램 내에서 외부 프로그램을 실행시키고 그 결과를 받아내는 것이다. 이미 알고 있는 사람들에게는 아주 쉬운 일이지만 한번도 사용해보지 않았다면 이번 기회에 익혀두도록 하자. 나중에 두고 두고 써먹을 수 있는 프로그램 기법이 될 것이다(실제로 필자도 위기가 닥칠 때마다 이용해서 아주 유용하게 사용하고 있다). 아래 자바 메소드는 실행할 외부 프로그램의 이름을 스트링으로 지정하고 그 프로그램을 실행 후에 표준 출력과 표준 에러를 받아 내는 것이 전부이다.

public void run() {
Runtime runtime = Runtime.getRuntime();
Process process = null;

try {
// this.command = "systeminfo.exe";
process = runtime.exec(this.command); // 외부 프로그램 실행
} catch (IOException ioe) {
ioe.printStackTrace();
}

// 표준 출력
InputStream standardOutput = process.getInputStream();
// 표준 에러
InputStream standardError = process.getErrorStream();

InputStreamReader ir = new InputStreamReader(standardOutput);
InputStreamReader ow = new InputStreamReader(standardError);

BufferedReader outReader = new BufferedReader(ir);
BufferedReader errorReader = new BufferedReader(ow);

StringBuffer stdout = new StringBuffer();
StringBuffer stderr = new StringBuffer();
String line = null;
try {
// 루프를 돌면서 퓨준 출력과 표준 에러를 계속 받아낸다
while ( (line = outReader.readLine()) != null) {
stdout.append(line).append("\n");
}
while ( (line = errorReader.readLine()) != null) {
stderr.append(line).append("\n");
}
standardOutput.close();
standardError.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
result.setStdout(stdout.toString()); // 이 결과를 나중에 사용한다
result.setStderr(stderr.toString());
}

위의 코드 마지막 부분에 나중에 사용할 결과를 지정하는 부분이 있다. 그 결과를 이용해서 원하는 정보만 가려내는 코드는 다음과 같다.

String result = pRunner.result.getStdout();
StringTokenizer st = new StringTokenizer(result, "\n");
while (st.hasMoreElements()) {
String line = (String)st.nextElement();
if (line.startsWith("호스트 이름")) {
addSysInfo(line);
}
if (line.startsWith("OS 이름")) {
addSysInfo(line);
}
if (line.startsWith("등록된 소유자")) {
addSysInfo(line);
}
if (line.startsWith("Product ID")) {
addSysInfo(line);
}
if (line.startsWith("System Up Time")) {
addSysInfo(line);
}
}

원하는 정보를 모두 얻었다면 이제 GUI로 아름답게 보여주는 일만 남았다. 이 부분에서는 여러 분들이 직접 원하는 형태대로 만들어보기 바란다.
<출처:ibm.com/developerworks/kr>
반응형

자바 프로그래머라면 당연히 AWT나 Swing 컴포넌트에 대해서 알고 있고 GUI를 위해서 여러 형태의 컴포넌트들을 조합해서 원하는 화면을 만들어 보았을 것이다. 그러나 때로는 JDK 에서 지원하는 표준 컴포넌트들만으로는 무엇인가 부족함을 느껴 본적은 없는가? 자신의 입맛에 딱 맞는 컴포넌트가 없어서 오랜 시간을 허비하거나 고생해본 경험이 있을 수도 있다. 이번 기사에서는 자신만의 간단한 컴포넌트를 작성해보기로 하자.

이번 소스에서 만들것은 CPU의 사용양을 윈도우의 작업 관리자에서 보이는 형태처럼 만드는 것이다. JProgressBar를 사용하면 비슷한 형태가 나오기는 하지만 아무래도 많이 다르다는 느낌이 들어서 직접 만들어서 사용하자.

import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.awt.event.*;

public class PmTickChartPanel extends JPanel {
BorderLayout borderLayout1 = new BorderLayout();
JPanel centerPanel = new JPanel();
JPanel southPanel = new JPanel();
JPanel northPanel = new JPanel();
JLabel dataLabel = new JLabel();
GridLayout gridLayout1 = new GridLayout();
BorderLayout borderLayout2 = new BorderLayout();
JLabel titleLabel = new JLabel();
BorderLayout borderLayout3 = new BorderLayout();
JPanel westPanel = new JPanel();
JPanel eastPanel = new JPanel();

// 편의상 눈금은 10개만 보이고 색상 변경도 10 단위로만
int tickCount = 10;

Border centerPanelBorder;
private Border border1;

public PmTickChartPanel() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}

private void jbInit() throws Exception {
centerPanelBorder = BorderFactory.createLineBorder(Color.green, 1);
border1 = BorderFactory.createBevelBorder(BevelBorder.LOWERED, new Color(4, 4, 4), new Color(3, 3, 3), Color.black, Color.black);
this.setBackground(Color.black);
this.setForeground(Color.green);
this.setBorder(border1);
this.setLayout(borderLayout1);
centerPanel.setBackground(Color.black);
centerPanel.setFont(new java.awt.Font("Dialog", 0, 12));
centerPanel.setForeground(Color.green);
centerPanel.setBorder(centerPanelBorder);
centerPanel.setLayout(gridLayout1);
southPanel.setBackground(Color.black);
southPanel.setForeground(Color.green);
southPanel.setLayout(borderLayout2);
northPanel.setBackground(Color.black);
northPanel.setForeground(Color.green);
northPanel.setLayout(borderLayout3);
dataLabel.setBackground(Color.black);
dataLabel.setFont(new java.awt.Font("Dialog", 1, 12));
dataLabel.setForeground(Color.green);
dataLabel.setHorizontalAlignment(SwingConstants.CENTER);
dataLabel.setHorizontalTextPosition(SwingConstants.CENTER);
dataLabel.setText("");
titleLabel.setBackground(Color.black);
titleLabel.setFont(new java.awt.Font("Dialog", 1, 12));
titleLabel.setForeground(Color.green);
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
titleLabel.setHorizontalTextPosition(SwingConstants.CENTER);
this.titleLabel.setText("CPU");
gridLayout1.setColumns(1);
gridLayout1.setRows(tickCount);
gridLayout1.setHgap(1);
gridLayout1.setVgap(1);
eastPanel.setBackground(Color.black);
eastPanel.setForeground(Color.green);
westPanel.setBackground(Color.black);
westPanel.setForeground(Color.green);
this.add(centerPanel, BorderLayout.CENTER);
this.add(southPanel, BorderLayout.SOUTH);
southPanel.add(dataLabel, BorderLayout.CENTER);
this.add(northPanel, BorderLayout.NORTH);
northPanel.add(titleLabel, BorderLayout.CENTER);
this.add(westPanel, BorderLayout.WEST);
this.add(eastPanel, BorderLayout.EAST);
setPreferredSize(new Dimension(90, 180));

for (int i = 0; i < tickCount; i++) {
Tick tick = new Tick(); // 눈금(tick)을 10개 생성하여 추가
this.centerPanel.add(tick);
}
}

/* 실제 컴포넌트에 값을 설정하면 눈금에 색상을 변경한다
* 값의 범위는 0~100 으로 하자
*/
public void setValue(int value) {
if (value > 100) { // 100을 넘어가면 100으로
value = 100;
}
else if (value < 0) { // 0보다 작으면 0으로
value = 0;
}

// 일단 전체 tick 을 검정색으로 칠하고
for (int j = 0; j < tickCount; j++) {
Tick tick = (Tick)this.centerPanel.getComponent(j);
tick.setBackground(Color.black);
tick.repaint();
}

// 입력된 value 값에 해당하는 tick들만 다시 녹색으로 칠한다
for (int i = 0; i < tickCount; i++) {
Tick tick = (Tick)this.centerPanel.getComponent(i);
if (tickCount - i > value / 10) {
// nothing to do
} else {
tick.setColor(Color.green);
tick.repaint();
}
}

// 하단에 숫자로 값을 표시
this.dataLabel.setText(value + " %");
}

public static void main(String args[]) {
JFrame frame = new JFrame(); // 테스트용 프레임을 생성하자
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
PmTickChartPanel tickPanel = new PmTickChartPanel();
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(tickPanel, BorderLayout.CENTER);

frame.setSize(300, 300);
frame.setVisible(true);

for (int i = 0 ; i < 100 ; i++) { // 테스트를 위해 값을 설정하는 부분
try {
Thread.sleep(100); // 잠시 쉬었다가
tickPanel.setValue(i); // 1씩 증가되는 값을 설정, 10 단위로 눈금 색상 변경
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}

/* 10 단위의 눈금 하나에 해당하는 컴포넌트
* 같은 값을 갖는 것이 좌우 하나씩 쌍으로 구성된다
*/
class Tick extends JPanel {
JPanel lPanel = new JPanel();
JPanel rPanel = new JPanel();
GridLayout layout = new GridLayout(1, 2);

public Tick() {
this.setBackground(Color.black);
this.setForeground(Color.black);
lPanel.setBackground(Color.black);
lPanel.setForeground(Color.green);
rPanel.setBackground(Color.black);
rPanel.setForeground(Color.green);
layout.setHgap(1);
setLayout(layout);
add(lPanel);
add(rPanel);
}

protected void setColor(Color color) {
lPanel.setBackground(color);
rPanel.setBackground(color);
}
}
<출처:ibm.com/developerworks/kr>

+ Recent posts