#!/usr/bin/ruby -w
#xmlrpc-upc.rb
require 'xmlrpc/client' #xml-rpc 사용!
require 'pp'  #pretty-printer를 사용합니다.

def find_product(upc)
 server = XMLRPC::Client.new2('http://www.upcdatabase.com/rpc')
 begin
  response = server.call('lookupUPC', upc)
  pp response        # 이쁘게 출력합뉘다.

 rescue XMLRPC::FaultException => e
  puts "오류 : "
  puts e.faultCode
  puts e.faultString
 end
end

#puts find_product("001441000055").each{}
#puts find_product("001441000055")['description']
#puts find_product("001441000055")['foundsize']
#puts find_product("001441000055")['size']
find_product("001441000055")

# "Trader Joe's Thai Rice Noodles"

저작자 표시 비영리
Posted by 티엘로

Here is a very simple yet complete working sample of a
low level Windows keyboard hook within a Swing application.
Please try it.

//
// FrameTest.java
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FrameTest extends JFrame {
private JPanel mainPanel;
private JTextArea mainTextArea;
private HookTest hook;

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FrameTest().setVisible(true);
}
});
}

FrameTest() {
super("FrameTest");
setSize(200, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainTextArea = new JTextArea();
mainPanel.add(mainTextArea, BorderLayout.CENTER);
getContentPane().add(mainPanel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
hook.unRegisterHook();
}
});
new Thread() {
public void run() {
hook = new HookTest();
hook.registerHook();
}
}.start();
}
}

//
// HookTest.java
//
public class HookTest {
static {
System.loadLibrary("HookTest");
}

void processKey(int key, boolean pressed) {
System.out.println("Java: HookTest.processKey - key = " + key +
(pressed ? " pressed" : " released"));
}

native void registerHook();
native void unRegisterHook();
}

//
// HookTest.h
//
#ifndef _Included_HookTest
#define _Included_HookTest

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL Java_HookTest_registerHook(JNIEnv * env, jobject
obj);

JNIEXPORT void JNICALL Java_HookTest_unRegisterHook(JNIEnv * env,
jobject obj);

#ifdef __cplusplus
}
#endif

#endif /* _Included_HookTest */

//
// HookTest.cpp
//
#include <windows.h>
#include "HookTest.h"

HINSTANCE hInst = NULL;
JavaVM * jvm = NULL;
jobject hookObj = NULL;
jmethodID processKeyID = NULL;
DWORD hookThreadId = 0;

extern "C" BOOL APIENTRY DllMain(HINSTANCE _hInst, DWORD reason, LPVOID
reserved) {
switch (reason) {
case DLL_PROCESS_ATTACH:
printf("C++: DllMain - DLL_PROCESS_ATTACH.\n");
hInst = _hInst;
break;
default:
break;
}

return TRUE;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam) {
JNIEnv * env;
KBDLLHOOKSTRUCT * p = (KBDLLHOOKSTRUCT *)lParam;

if (jvm->AttachCurrentThread((void **)&env, NULL) >= 0) {
switch (wParam) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
printf("C++: LowLevelKeyboardProc - Key pressed\n");
env->CallVoidMethod(hookObj, processKeyID, p->vkCode,
true);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
printf("C++: LowLevelKeyboardProc - Key released\n");
env->CallVoidMethod(hookObj, processKeyID, p->vkCode,
false);
break;
default:
break;
}
}
else {
printf("C++: LowLevelKeyboardProc - Error on the attach current
thread.\n");
}

return CallNextHookEx(NULL, nCode, wParam, lParam);
}

void MsgLoop() {
MSG message;

while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}

JNIEXPORT void JNICALL Java_HookTest_registerHook(JNIEnv * env, jobject
obj) {
HHOOK hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardProc, hInst, 0);

if (hookHandle == NULL) {
printf("C++: Java_HookTest_registerHook - Hook failed!\n");
return;
}
else {
printf("C++: Java_HookTest_registerHook - Hook successful\n");
}

hookObj = env->NewGlobalRef(obj);
jclass cls = env->GetObjectClass(hookObj);
processKeyID = env->GetMethodID(cls, "processKey", "(IZ)V");
env->GetJavaVM(&jvm);
hookThreadId = GetCurrentThreadId();

MsgLoop();

if (!UnhookWindowsHookEx(hookHandle))
printf("C++: Java_HookTest_registerHook - Unhook failed\n");

else
printf("C++: Java_HookTest_registerHook - Unhook
successful\n");
}

JNIEXPORT void JNICALL Java_HookTest_unRegisterHook(JNIEnv *env,
jobject object) {
if (hookThreadId == 0)
return;

printf("C++: Java_HookTest_unRegisterHook - call
PostThreadMessage.\n");
PostThreadMessage(hookThreadId, WM_QUIT, 0, 0L);
}


Regards


참조 : http://www.velocityreviews.com/forums/t360927-setwindowshookex-not-notifing-me-on-key-pressed-using-jni-and-c-dll.html

 

저작자 표시 비영리
Posted by 티엘로

루비(Ruby) 프로그래밍

루비 변수, 쿼트, 어레이, 객체, 메소드

developerWorks
문서 옵션
수평출력으로 설정

이 페이지 출력

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기


제안 및 의견
피드백

난이도 : 초급

Joshua D. Drake, 프로젝트 매니저, Command Prompt, Inc

2001 년 8 월 01 일

Linux Networking HOWTO, Linux PPP HOWTO, Linux Consultants HOWTO의 저자이자 Command Prompt, Inc 의 공동 창업자인 Joshua Drake가 Ruby 프로그래밍을 설명한다. 다른 언어 사용자라도 이 글을 통해 유용한 정보를 얻을 수 있을 것이다.

루비(Ruby)는 일본의 Yukihiro Matsumoto가 개발한 순수한 객체 지향 스크립팅 언어이다. 텍스트 프로세싱과 시스템 관리 태스크를 핸들하도록 디자인되었다.

아래 예제에서 보듯이, 펄 또는 PHP 같은 스크립팅 언어를 작성해 본 경험이 있는 사람이라면 루비 신택스도 익숙할 것이다. 그러나, 펄 또는 PHP와는 다르게, 라인 종결자로 세미 콜론(semi-colon)을 사용해야 한다. 어떤 개발자들은 이런 사실 때문에 혼란스러워 할 수도 있지만 실제로 이것은 개발 속도를 높일 수 있다.


Listing 1. Hello world
#!/usr/bin/ruby
#
# My first ruby program
#
print "Hello World\n"


Listing 2. 아웃풋 변경하기
#!/usr/bin/ruby
#
# My first ruby program
#

# Declare our salutation

$salut = "Good Bye World\n"

# Prepare statements

 print "Hello World\n"
 print $salut

Using the $salut 변수를 사용하여 언제라도 두 번째 print 문장을 쉽게 변경할 수 있다. 프로그램의 어떤 지점에서도 변수를 선언할 수 있다.


Listing 3. 변수 선언하기
#!/usr/bin/ruby
#
# My first ruby program
#

$salut = "Good Bye World\n"

 print "Hello World\n"
 print $salut

#
# Declare a new value for $salut.
#

$salut = "Oh, I am sorry. I didn't mean to warn
you...\n"

 print "What do you mean Good Bye World?\n"
 print $salut

위 예제를 실행하면 아웃풋은 다음과 같다:


Hello World
Good Bye World
What do you mean Good Bye World?
Oh, I am sorry. I didn't mean to warn you...

변수 재지정(re-assignment)이 작동한다.




위로


싱글 쿼트(single quote) & 더블 쿼트(double quote)

대부분의 언어가 그렇듯, 루비도 싱글 쿼트와 더블 쿼트가 구별된다. 루비에서 더블 쿼트는 "루비는 쿼트 안에 있는 모든 값을 인터프리팅한다"는 것을 의미한다:


print "Hello World\n"

루비 인터프리터는 \n 을 이스케이핑 하지 않고 대신 새로운 라인을 STDOUT (Standard Out)에 프린트 할 것이다. 하지만 싱글 쿼트로 같은 문장을 실행시키면 다음과 같다:


print 'Hello World\n'

루비는 다음과 같이 아웃풋을 만들것이다:


Hello World\n

새로운 라인이 프린트되지 않았다는 것을 주목하라. 대신 루비는 전체 문장이 리터럴(literal)이라고 생각한다. 이것은 펄이 사용하는 것과 같은 기능이다.




위로


단어 수학

루비에서 모든 스트링은 연산자를 사용할 수 있다. 다시 말해서 단어에 대해 수학을 사용할 수 있다는 의미이다. 예를 들어:


$salut = $salut * 3

결과는 다음과 같다:


Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...

그리고


$salut = $salut + " 10, 9, 8..."

 print $salut

다음과 같이 결과가 나온다:


Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
 10, 9, 8...

변수가 세번 프린트되었지만, "10, 9, 8..."은 프로그램의 끝에 한 번만 프린트되었다. 이유는 무엇일까?

이유는 "10, 9, 8..." 을 변수의 끝에 추가했기 때문이다. 변수에게 "10, 9, 8..."을 각 라인에 추가하라고 명령하지 않았다.

"What do you mean Good Bye World? \n" 에서 "Hello World\n" 로 바꾸었을 때 설명했지만, 일단 변수가 지정되면 그 변수가 재 지정(reassigned)되지 않는 한 정적(static)이다. 하지만 이것은 멀티플라이어(multiplier) 또는 연결(concatenation)이 변수와 함께 사용되는 경우를 의미하지는 않는다. 변수와 함께 연결(+ 표시)을 사용하면 이전에 지정된 변수와 지정된 변수에 추가된 스트링을 변수가 상속받을 수 있다. 우리의 경우, " 10, 9, 8..." 이다.




위로


어레이

$salut 변수를 여러번 재지정해야 한다면? 대부분 그런일은 발생하기 마련이다. 따라서 변수를 재지정하는 대신, 모든 변수 값을 어레이에 놓을 수 있다.

어레이는 각 변수의 값이 개별적으로 어드레스(address) 할 수 있도록 한다. 다음 예제를 보자:


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print $salut

위에 대한 결과 아웃풋은 다음과 같다:


Hello WorldGood Bye WorldWhat do you mean Good Bye
World?

원하던 아웃풋이 아니다. 공간이나 새로운 라인이 없다. 따라서 우리는 어떤 부분의 어레이를 디스플레이 할지 정할 수 있고 아웃풋을 읽을 수 있도록 하기 위해서 연결(concatenation)을 사용할 수 있다.


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print $salut[0] + "\n"
 print $salut[1] + "\n"
 print $salut[2] + "\n"

아웃풋은 다음과 같다:


Hello World
Good Bye World
What do you mean Good Bye World?

코드를 분석해보자:


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

루비에서는 다음의 값을 갖고 있는 salut 변수를 지정할 수 있다:

$salut = 0 1 2
Hello World Good Bye World What do you mean Good Bye World?

0

으로 시작하고 이것에서 부터 늘어난다. 어레이의 두 번째 값을 프린트하기 위해 다음과 같이 타이핑한다:


 print $salut[1]




위로


IF, ELSE 조건

루비에서 데이터를 나타내는 기초를 살펴보았다. 이제 루비 프로그램의 로직에 대해 살펴보자. 말하자면 프로그래머에게 받은 결과에 근거한 기본 함수작동을 수행하도록 지시하는 것이다. 또한 루비 프로그램이 사용자에게 받은 결과에 대한 조건을 수행하는 방법도 살펴 볼 것이다. 새로운 코드가 이 예제에 사용될 것이다.


Listing 4. 결과에 근거한 기본 함수 수행하기
$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print "When you enter the world, what do you say? "
 while enterWorld = STDIN.gets
   enterWorld.chop!
   if enterWorld == $salut[0]
     print "\n" + "Yes. Hello World would be
polite.\n"
     break
   else
     print "You say '", enterWorld, "'?!\n" + "You
humans are so rude!\n"
   end
  end

루비 개발의 새로운 면이 위 코드에 많이 소개되었다.


예제
#!/usr/bin/ruby
#
# My first interactive ruby script
#

# Define our main variable with an array

$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

# Print my first question

 print "When you enter the world, what do you say? "

# Create a while loop with the object enterWorld and
await data from
# standard input. The while loop will make sure that
ruby continues
# to process the application until the program tells
it to stop.

 while enterWorld = STDIN.gets

# Make sure we use the chop method on the enterWorld
object. The use
# of the chop method will insure that we strip new
lines and carriage
# returns from our input.

# You will notice that using the chop method has an
extra
# character. The ! allows the existing object to be
modified
# by the method. If you did not use the !, you would
have to redeclare
# the enterWorld object for the if condition to
correctly occur.

   enterWorld.chop!

# Begin the condition sequence. Basically, if
enterworld equals
# Hello World, which is 0, within the array, print
# a new line. Then print, "Yes, Hello World would be
polite." to the screen.

   if enterWorld == $salut[0]
     print "\n" + "Yes. Hello World would be
polite.\n"

# The break statement tells ruby to stop executing if
the previous
# condition is met. If we did not include this in our
while loop,
# the program would run continuously.

    break

# The else statement is used as the secondary
condition. In other
# words, if the first condition is not met, please do
the following.

   else
     print "You say '", enterWorld, "'?!\n" + "You
humans are so rude!\n"
   break

# The end statement is used to close a condition or
loop. In our case,
# it is being used to close both. We are first closing
our if
# condition statements and then stopping our while
loop.

   end
  end




위로


객체와 메소드

이 코드에 사용된 몇 가지의 기술과 방법들은 여러분에게 생소할 수도 있다. 루비는 객체 지향 프로그래밍(OOP) 언어이다. OOP를 사용한다는 것은 일반적으로 객체와 매소드 같은 아이템을 호출하는 것이다. 객체(object)는 콘테이너와 같다. 이것은 변수와 함수를 포함하고 있다. 매소드(method) 는 객체를 어드레싱하는 함수와 같은 것이다. 이전 예제에서, 객체와 메소드가 모두 실행되는 것을 보여줄 수 있다.


1
while enterWorld = STDIN.gets
   enterWorld.chop!

두 개의 객체와 두 개의 메소드가 있다. 첫 번째 객체는 enterWorld 이고 두 번째 객체는 STDIN 이다. enterWorld 객체는 사용자 정의 객체이고 STDIN 객체는 루비에 구현되어 있다.

예제에는 두 개의 메소드도 있다. 첫 번째는 gets 이고 두 번째는 chop!이다. 앞서 언급했지만 메소드는 객체를 어드레싱 한다. 특히 메소드는 객체 안에서 액션을 수행한다. gets 메소드를 사용하여 루비에게 STDIN을 얻도록(get) 명령할 수 있다. 루비가 STDIN 과 관련된 gets를 보면, 키보드 인풋과 캐리지 리턴(carriage return)을 기다릴 것이다. STDIN.gets은 사용자가 무언가를 타이핑하고 엔터를 치기를 기다린다.

두 번째 메소드인 chop!은 사용자 정의 객체인 enterWorld를 어드레싱 한다. chop! 메소드는 enterWorld에게 enterWorld 객체와 관련된 데이터에서 새로운 라인과 캐리지리턴으로 자르도록 (chop) 명령한다. 이전의 코드에서chop! (또는 chomp!)을 사용하지 않는다면 "true"가 결코 될 수 없다.


 if enterWorld == $salut[0]

chop!를 사용하지 않고 $salut[0]이 실제로 $salut[0]\n와 같기 때문에 "false"가 된다. 새로운 라인은 STDIN 객체가 gets 메소드에서 받은 인풋에 의해 생겨난다. 캐리지 리턴을 사용하면 새로운 라인 문자들을 값의 끝에 추가하게 된다.




위로


결론

루비는 매우 강력하지만 사용하기가 쉽지만은 않다. C++, Perl, Python 프로그래밍 경험이 있다면 그러한 언어들과 루비와의 상당한 유사성을 발견하게 될 것이다 (특히 Python).



참고자료



필자소개

Joshua Drake는 Command Prompt, Inc의 공동 창립자이다. PostgreSQL과 리눅스 개발을 하고 있다. Linux Networking HOWTO, Linux PPP HOWTO, Linux Consultants HOWTO의 저자이기도 하다.

저작자 표시 비영리
Posted by 티엘로

원문 -> http://linuxgazette.net/issue83/sandeep.html

-----------------------------------------------------------------------------

   이전 part1에서 우리는 ptrace의 기본적인 특성에 대해서 알아 보았습니다. 우리는 이제
  다시한번 작은 예제를 볼 것입니다. 제가 미리 말 한것 처럼 ptrace의 메인 어플리케이션
  은 실행될 프로세스의 메모리나 레지스터에 접근하는 것입니다.(그것이 디버깅의 목적
  이든 나쁜목적이든 말입니다.) 그래서 먼저 우리는 몇가지 기본적인 실행파일의 바이너리
  구조에 대해서 알 필요가 있습니다.- 그 다음 우리가 알 것은 어떻게 그리고 어디에 접근
  해야 하는것입니다.. 그래서 저는 먼저 ELF의 기본적인 튜터리얼을 제공할 것입니다.
  ELF는 리눅스에서 사용되는 바이너리 포맷입니다. 이 문서의 끝 부분에서 우리는 다른
  프로세스의 메모리와 레지스터에 접근하여 그들에게 추가적인 코드를 주입함으로 써
  출력을 다르게 만들어 볼 것입니다.

    NOTE. 혼란 스러워하지 마세요!! 확실히 이 문서는  ptrace에 관한 것이지 ELF에 관한
    것이 아닙니다. 그러나 ELF의 기본적인 지식이 프로세스의 이미지에 접근한데 필요
    합니다. 그래서 이것을 먼저 설명하는 것입니다.

1. What is ELF?

        ELF는 Executale and Linking Format 입니다. 이것은 리눅스에서 사용되는 실행
        가능한 바이너리를 정의합니다 - 그리고 공유 오브젝트와 코어 덤프 파일, 재배치
        들도 정의합니다. ELF는 링커와 로더에 의해 모두 사용됩니다. 그들은 두 가지 측면
        으로부터 ELF를 보게 됩니다. 그래서 둘 다 일반적인 인터페이스를 가집니다.

        ELF의 구조는 많은 섹션과 세그먼트를 가집니다. 재배치 파일은 섹션 헤더 테이블을
        가지고 실행가능한 파일은 프로그램 헤더 테이블을 가지고, 공유 오브젝트 파일은 둘
        다 가지고 있습니다. 다음에 오는 섹션에서는 이 헤더들이 무엇인지 설명을 하겠습니다.


2. ELF Headers
 
    모든 ELF 파일은 ELF 헤더를 가지고 있습니다. 이것은 항상 0 오프셋(파일의 가장 처음
    부분)에 있습니다. 이것은 바이너리 파일의 중요한 사항을 가지고 있습니다. - 무슨 자료
    구조들이 파일과 관련되었는지 알기 위해서는 꼭 인터럽트 되어야 합니다.(참조 되어야
    합니다)

    헤더의 포맷은 아래와 같습니다.(이 파일은 /usr/src/include/linux/elf.h에 있습니다)

   --------------------------------------------------------
   #define EI_NIDENT       16

   typedef struct elf32_hdr{
         unsigned char e_ident[EI_NIDENT];
          Elf32_Half    e_type;
          Elf32_Half    e_machine;
          Elf32_Word    e_version;
          Elf32_Addr    e_entry;  /* Entry point */
          Elf32_Off     e_phoff;
          Elf32_Off     e_shoff;
          Elf32_Word    e_flags;
          Elf32_Half    e_ehsize;
          Elf32_Half    e_phentsize;
          Elf32_Half    e_phnum;
          Elf32_Half    e_shentsize;
          Elf32_Half    e_shnum;
          Elf32_Half    e_shstrndx;
   } Elf32_Ehdr;
   --------------------------------------------------------

    각각의 필드에 대해서 간단히 설명하면 다음과 같습니다

    1. e_ident : 바이너리 파일을 어떻게 다루어야 할지에 대한 정보가 담겨 있습니다
                 플랫폼에 의존적입니다
   
    2. e_type : 바이너리 파일을 어떻게 사용해야 할지에 대한 정보가 담겨 있고 타입은
                재배치 가능한지, 실행가능한지, 공유가능한지 그리고 코어파일인지 입니다
   
    3. e_machine : 예상했던데로 이 필드는 아키텍쳐를 나타냅니다 - Intel 386, Alpha, Sparc

    4. e_version : 오브젝트 파일의 버전을 나타냅니다

    5. e_phoff : 프로그램 헤더의 시작 오프셋을 가지고 있습니다

    6. e_shoff : 섹션 헤더의 시작 오프셋을 가지고 있습니다

    7. e_flags : 프로세서 의존적인 플래그이다. i386에서는 사용되지 않습니다

    8. e_ehsize : ELF헤더의 size를 가지고 있습니다

    9. e_phentsize & e_shentsize : 프로그램 헤더와 섹션헤더의 size를 나타냅니다

    10. e_phnum & e_shnum : 프로그램 헤더아 섹션헤더의 갯수를 나타내며. 프로그램 헤더
                     테이블은 프로그램 헤더의 배열입니다. 비슷하게 섹션헤더도 마찬가지
                                     입니다
   
    11. e_shstrndx : 섹션 헤더 테이블안에서 섹션이 가지고 있는 섹션의 이름입니다. 이것은
                    테이블안의 섹션을 가리키는 인덱스 입니다
                                    (아래에서 좀더 볼 것이다)
                                   

3. Sections And Segments

    위에서 말 한것 처럼 링커는 섹션 헤더 테이블에서 묘사된것 처럼 논리적인 헤더의 집합
    인것 처럼 파일을 다룹니다 어플리케이션 들은 아마도 고유의 방법으로 인터럽트를 할 것
    입니다.

    섹션헤더들의 배열인 섹션헤더 테이블이 있습니다. 이 테이블의 가장 첫번째 인 0 엔트리는
    항상 NULL 이고 바이너리의 어느 부분도 나타내지 않습니다. 각각 섹션 헤더는 다음과 같은
    포맷을 가집니다.


   --------------------------------------------------------
    typedef struct elf32_shdr {
         Elf32_Word sh_name;           /* Section name, index in string tbl (yes Elf32) */
         Elf32_Word sh_type;           /* Type of section (yes Elf32) */
         Elf32_Word sh_flags;          /* Miscellaneous section attributes */
         Elf32_Addr sh_addr;           /* Section virtual addr at execution */
         Elf32_Off sh_offset;          /* Section file offset */
         Elf32_Word sh_size;           /* Size of section in bytes */
         Elf32_Word sh_link;           /* Index of another section (yes Elf32) */
         Elf32_Word sh_info;           /* Additional section information (yes Elf32) */
         Elf32_Word sh_addralign;      /* Section alignment */
         Elf32_Word sh_entsize;        /* Entry size if section holds table */
    } Elf32_Shdr;
   --------------------------------------------------------

  이제 각 필드의 자세한 설명을 봅시다.

    1. sh_name : 이것은 해당 인덱스의 e_shstrndx 문자열 테이블의 내용을 가집니다. 이 인덱스는
              Null로 끝나는 스트링의 시작 부분이며 이것은 섹션의 이름으로 사용됩니다. 많은
                        섹션 이름들이 있으며 아래는 그 중 일부 입니다.

                        .text : 이 섹션은 프로그램의 실행가능한 명령어를 가집니다.
                        .data : 이 섹션은 프로그램 이미지에 사용되는 초기화 된 자료를 가집니다.
                        .init : 이 섹션은 프로세스 초기화에 관련된 코드를 가집니다.

    2. sh_type : 프로그램 데이타, 심볼테이블, 스트링 테이블 등 섹션의 타입을 나타냅니다.

    3. sh_flags : 섹션의 내용을 어떻게 다룰 것인지에 대한 정보를 가집니다.

    4. sh_addralign : 섹션 내용을이 어떤 정렬방법이 요구되는지 나타냅니다.. 일반적으로 0/1
                 (둘 다 정렬을 하지 않는다는 의미) 또는 4를 사용합니다

  나머지 필드는 스스로 찾아 봅시다

    3.2. ELF 세그먼트 와 프로그램 헤더들

    ELF 세그먼트들은 로딩되는 중에 사용됩니다 ie. 프로세스 이미지가 코어안에서 만들어 질때
    각각 세그먼트는 프로그램 헤더에 의해서 묘사 됩니다. 프로그램 헤더 테이블이라는 것이 존재
    하는데(보통 ELF 헤더 근처에 있습니다) 테이블은 프로그램 헤더들의 배열입니다. 프로그램 헤더
    는 다음과 같은 포맷을 가집니다.

    --------------------------------------------------------
    typedef struct
    {
             Elf32_Word    p_type;                 /* Segment type */
             Elf32_Off     p_offset;               /* Segment file offset */
             Elf32_Addr    p_vaddr;                /* Segment virtual address */
             Elf32_Addr    p_paddr;                /* Segment physical address */
             Elf32_Word    p_filesz;               /* Segment size in file */
             Elf32_Word    p_memsz;                /* Segment size in memory */
             Elf32_Word    p_flags;                /* Segment flags */
             Elf32_Word    p_align;                /* Segment alignment */
    } Elf32_Phdr;
    --------------------------------------------------------

    1. p_type : 내용을 어떻게 다룰 것인지에 대한 정보를 제공합니다. 이것은 다음과 같은 프로그램의
                타입을 제공합니다.

                            - unused
                            - loadable
                            - Dynamic linking information
                            - reserved

                            etc ..

    2. p_vaddr : 세그먼트가 로드 될 것으로 예상되는 가상 메모리 주소 입니다.

    3. p_paddr : 세그먼트가 로드 될 것으로 예상되는 물리 메모리 주소입니다.
                 (역자 주. i386 리눅스는 가상메모리만을 사용하기 때문에 실제 p_paddr은 p_vaddr과
                               동일한 값을 가집니다.)
   
  4. p_flags : 보호 플래그를 가집니다. - read/write/execute 권한

    5. p_align : 메모리안의 세그먼트 정렬에 관한 내용을 가집니다. 만약 세그먼트가 loadable 타입
                 이라면 정렬은 page 크기로 예측될 수 있습니다.
   
    나머지 필드는 직접 알아내 봅시다 :D

4. Loading the ELF File

  우리는 ELF 오브젝트 파일에 대한 어느정도 지식을 가지게 되었습니다. 이제 우리는 실행을 위해
    파일이 어떻게 그리고 어디에로드 되는지 알아야 합니다. 보통 우리는 단순히 프로그램 이름을
    쉘 프롬프트에 입력합니다. 사실 많은 흥미있는 것들이 엔터를 친 후에 일어나게 됩니다.

    먼저 쉘은 커널 루틴을 호출하는 표준 libc 함수를 호출 합니다. 이제 공(역자 주 - 프로그램의
    흐름을 말하겠죠??)은 커널의 코트로 넘어왔습니다. 커널은 파일을 열고 실행파일의 타입과 포맷
    을 알아냅니다. 그리고는 ELF와 요구되는 라이브러리들을 로드하고 프로그램의 스택을 초기화
    하며 마침내 프로그램 코드에게 컨트롤을 넘깁니다.

    프로그램은 0x8048000에 로드되고(이것은 /proc/PID/maps로 확인할 수 있습니다) 프로그램의
    스택은 0xbfffffff에서 시작합니다.

5. Code Injection

   우리는 메모리에 프로그램이 로드되는 것을 자세히 보았습니다. 그래서 프로세스가 주어지고
   이것의 메모리 공간을 알고 있을때 우리는 이것을 추적할 수 있으며(만약 권한을 우리가 가지고
   있을경우) 프로세스의 개인적인 자료구조에 접근할 수 있습니다. 이것은 말이 쉽지 실제로
   하기에는 쉽지 않습니다. 한번 시도해 보지 않겠습니까??
   가장 먼저 다른 프로그램의 레지스터에 접근하고 이것을 수정하는 프로그램을 작성해 봅시다.
   여기서 우리는 다음과 같은 request 값을 사용할 것입니다.

     - PTRACE_ATTACH : 특정 pid의 프로세스를 붙입니다.
     - PTRACE_DETACH : 특정 pid의 프로세스를 때어냅니다.

       NOTE. 이것을(역자 주- PTRACE_DETACH를 말하는듯?) 호출하는 것을 잊지 마십시오.
                 그렇지 않으면 프로세스는 정지 모드로 있을것이며 이것은 복구하기 힘듭니다.

     - PTRACE_GETREGS : 프로세스의 레지스터를 data에 의해 가리켜지는 구조체에 복사합니다
                                  (여기서 addr 인자는 무시됩니다.). 이 구조체는 user_regs_struct 이며
                                  다음과 같이  정의되어 있습니다. 이것은 asm/user.h 에 있습니다.

    --------------------------------------------------------
    struct user_regs_struct {
                long ebx, ecx, edx, esi, edi, ebp, eax;
                unsigned short ds, __ds, es, __es;
                unsigned short fs, __fs, gs, __gs;
                long orig_eax, eip;
                unsigned short cs, __cs;
                long eflags, esp;
                unsigned short ss, __ss;
       };
    --------------------------------------------------------

    - PTRACE_SETREGS : 이것은 GETREGS의 반대 입니다.
    - PTRACE_POKETEXT : 이것은 추적되는 프로세스의 addr 주소안에 있는 데이타에 의해 가리켜
                              지는 곳에서 32bit를 복사합니다.
   
    이제 우리는 우리의 작은 코드 조각을 추적될 프로세스의 이미지에 삽입하고 강제로 프로세스의
    명령어 포인터(역자 주 - EIP를 말하는 것이겠죠?)를 변경시켜서 우리의 코드를 실행하게 만들
    것입니다. 이제 프로세스를 실행시키고 삽입된 코드를 실행시킬 것입니다.

    우리는 두가지 소스 파일을 가지고 있습니다. 한 가지는 추적되는 프로세스에 삽입될 어셈블리코드
    입니다. 우리가 추적할 조그마한 프로그램을 제공합니다.
    (역자 주 - 프로그램 소스들은 모두 현재 이 포스트에 첨부파일로 올리겠습니다 :D)

    소스 파일은 다음과 같습니다

      - Tracer.c
        - Code.S
        - Sample.c

  이제 파일을 컴파일 합니다.

  ---------------------------------
    #cc Sample.c -o loop
    #cc Tracer.c Code.S -o catch
    ---------------------------------

    이제 다른 콘솔로 가서 샘플 프로그램을 다음과 같이 실행합니다.

  ---------------------------------
    #./loop
    ---------------------------------

    다시 처음 콘솔로 돌아와서 loop 프로그램을 잡아서 이것의 출력을 변경할 프로그램을 다음과 같이
    실행합니다.

    ----------------------------------------------------
    #./catch `ps ax | grep "loop" | cut -f 3 -d ' '`
    ----------------------------------------------------
    (역자 주 - 그냥 직접 PID를 알아내서 입력해도 되겠죠 :D)

    이제 loop가 실행되고 있는 콘솔로가서 이것의 출력이 어떻게 변하였는지 확인해 봅니다.
    ptrace와의 놀이가 이제 시작되었습니다.

6. Looking Forward

  첫번째 파트에서 우리는 프로세스를 추적하고 이것의 명령어 갯수를 카운트 하였습니다. 이
  파트에서 우리는 ELF파일에 대해서 공부하고 작은 코드 조각을 프로세스에 주입 해 보았습니다.
  다음 장에서 저는 어떤 프로세스의 메모리 공간에 접근해 볼 것입니다.
 
그럼 그때까지 안녕히 계세요

    from Sandeep S.

※ 역자 주 - 이 문서의 아이디어는 매우 좋습니다. 마치 윈도우에서 원격에서 쓰레드를 만들어서 코드를 주입하는 것과 비교할 수 있겠습니다. 그러나 문서에서는 자세한 내용을 다루지 못하고 있습니다 .. 

단순히 아이디어만을 제공한 수준 같군요 ..프로그램이 실제 main()으로 넘어오는 과정도 자세히 설명하면 매우 복잡하고 알면 좋은 지식이니 따로 찾아서 공부해볼 필요가 있을것 같고 ..실제 코드를 주입하는 Tracer의 경우 현재의 리눅스에서 사용하기 위해서는 변형이 필요할 것으로 보입니다.
                    
 
저작자 표시 비영리
Posted by 티엘로


FTP? 자바?

FTP는 요즘 같은 인터넷 세상에서 빠지지 않는 프로토콜이다. FTP가 무엇인지 잘 모른다면 다음을 참고하자.
FTP (File Transfer Protocol) ; 파일 전송 프로토콜

FTP[에프 티 피]는 인터넷상의 컴퓨터들간에 파일을 교환하기 위한 표준 프로토콜로서 가장 간단한 방법이기도 하다. 화면에 표시할 수 있는 웹 페이지와 관련 파일들을 전송하는 HTTP (Hypertext Transfer Protocol), 전자우편을 전송하는 SMTP (Simple Mail Transfer Protocol)등과 같이, FTP도 역시 인터넷의 TCP/IP 응용 프로토콜 중의 하나이다. FTP는 웹 페이지 파일들을 인터넷상에서 모든 사람이 볼 수 있도록 하기 위해 저작자의 컴퓨터로부터 서버로 옮기는 과정에서 사용된다. 또한, 다른 서버들로부터 자신의 컴퓨터로 프로그램이나 파일들을 다운로드 하는 데에도 많이 사용된다.

사용자 입장에서는 간단한 명령어를 통하여 FTP를 쓰거나, 또는 그래픽 사용자 인터페이스를 제공하는 상용 프로그램을 쓸 수도 있다. 보통은 웹 브라우저도 웹 페이지로부터 선택한 프로그램을 다운로드 하는데 FTP를 사용한다. FTP를 사용하여 서버에 있는 파일을 지우거나 이름을 바꾸거나 옮기거나 복사하는 등 갱신작업을 할 수도 있다. FTP 서버에는 로그온을 해야 하지만, 익명의 FTP를 사용하여 모든 사람들에게 공개된 파일들을 쉽게 접근할 수 있도록 하고 있다.

FTP는 보통 TCP/IP에 함께 딸려오는 일련의 프로그램 속에 포함되어 있다.
간단히 말해서 FTP는 파일 전송 프로토콜이다. 우리는 FTP라는 프로토콜을 알게 모르게 많이 사용하고 있다. 회사 동료들 사이에 문서를 주고 받거나, 친구들과 음악 파일, 동영상 등을 주고 받는데 항상 사용하고 있는 것이다. 일반 컴퓨터 사용자들은 프로토콜이니 그런 것에는 관심 없을 것이다. 내가 원하는 파일을 주고 받기만 하면 될 뿐이니까… 그래도 FTP를 사용하기 위해서는 기본 명령을 알아야 한다. 하지만 이런 기본 명령 조차도 귀찮을 다름이다.

FTP 클라이언트 프로그램을 사용하면 FTP 명령을 알지 못하는 사람들도 GUI 환경에서 쉽게 FTP 서버에 접속해서 원하는 파일들을 주고 받을 수 있다. 일반적으로 많이 사용되는 FTP 클라이언트 프로그램으로는 WS_FTP, CuteFTP, 알FTP 등이 있다. 그렇다면 과연 누가 이런 FTP 클라이언트 프로그램을 만드는가? 당연히 개발자의 몫이다. 그럼 또한 자바로는 가능한가. 당연히 자바로도 가능하다. 원래 자바라는 언어 자체가 네트워크 분야에서 강력한 힘을 발휘한다고 하지 않는가? 이제부터 우리는 자바로 FTP 클라이언트 프로그램을 개발해 볼 것이다. 물론 다른 상용 프로그램처럼 훌륭한 GUI를 지원하는 프로그램은 아니다. 콘솔에서 작동하는 “Hello FTP”를 개발할 것이다. “에이, GUI가 없다면 썰렁할텐데…” 물론 이렇게 생각하는 분들도 있을 것이다. 하지만 모든 프로그램은 항상 “Hello”로부터 시작되므로 무시해서는 안될 것이다. 화려한 GUI 개발은 여러분들이 직접 해보시길 바란다. 아마 쉽지 않은 작업이 분명할 듯…

무엇이 필요한가?

당연히 자바로 개발하기 위해서는 JDK가 있어야 한다. JDK를 구하고 설치하는 것은 다른 자바 기초 서적을 참고하기 바란다.

자바만으로도 FTP 관련 프로그램을 만들 수 는 있다. sun.net.ftp 패키지에 보면 FTP 클라이언트 구현을 위한 클래스들이 있다. 하지만 필자가 프로젝트를 하면서 이 패키지를 사용해 보았는데, 몇몇 기능이 원하는 기능을 지원하지 않는 것을 알게 되었다. 그리고 썬사의 문서를 참고하면 sun으로 시작되는 패키지는 사용하지 말라고 권하고 있다.

아… 그렇다면 어찌해야 한단 말인가?
FTP 프로토콜을 지원하는 모든 기능을 다 구현해야 한다는 말인가? 충분한 시간과 실력이 된다면 그것도 좋은 방법이다. 일단 실력은 둘째 치고라도 우리에게는 충분한 시간이 없다. 이럴 때 도움을 받을 수 있는 수 많은 오픈 소스들과 공짜 패키지 들이 있지 않은가? 비겁하고 치사하다고 생각할 필요는 없다고 생각하자. 어차피 우리는 생활에 필요한 대부분의 것을 남이 만든 것을 사다 쓰고 있는 현실이니…

http://www.savarese.org/java/index.html에 가면 NetComponents에 대한 설명이 있다. 자세한 것은 읽어보면 알겠지만 소스 코드까지 무료로 사용할 수 있다. 우리는 이것을 사용할 것이다. http://www.savarese.org/downloads/NetComponents/에서 다운로드 받으면 된다. 필자는 NetComponents-1.3.8-bin.zip 파일을 다운로드 받아서 압축을 풀었다. 여러 폴더와 파일들이 있다. 필자는 윈도우를 사용하고 있다. 혹시 다른 운영체제를 사용한다면 문서들을 살펴보길 바란다.

NetComponents.jar 파일을 클래스패스에 추가하자. 클래스패스에 추가하는 방법을 모르는 분들은 다른 자바 기초 서적을 참고하시길… Doc 폴더에는 API 도움말이 있고 examples 폴더에는 여러 예제가 있다. 눈치 빠른 개발자들이라면 예제 파일을 본 후에 NetComponents가 아주 많은 프로토콜을 지원한다는 것을 쉽게 예상 할 수 있을 것이다. 공짜로 사용하는 것 치고는 아주 많은 기능을 제공한다. 여유가 되는 분들은 다른 기능도 사용해보고 이에 대한 기사 올려준다면 다른 개발자들에게 큰 힘이 될 것이 분명하다. 물론 예제에는 FTP도 포함되어 있으며(ftp.java) 본 기사에서도 이 예제를 참고할 것이다.

어떤 기능을 개발할 것인가?

프로그램을 개발하기 위해서는 어떤 것을 개발할 것인지, 어떤 기능을 수행해야 하는지를 명확히 알아야 한다. 이런 것들을 소프트웨어 공학에서는 “요구 사항” 이라고 한다. 요구 사항이 명확히 정의 되지 않으면 개발 도중에 많은 실수를 반복하고 기간이 늘어나기 쉽상이지만 우리가 개발할 프로그램의 요구 사항은 아래와 같이 간단하다.
  • FTP 서버에 접속한다.
  • 정해진 디렉토리로 이동한다.
  • 디렉토리 내의 사이즈가 0보다 큰 모든 로그 파일들을 가져온다.
혹시 다른 기능이 더 필요하다면 API 도움말을 참고하면 된다. 적절한 클래스와 메소드들을 사용해서 상용 FTP 클라이언트 프로그램들이 제공하는 기능은 대부부분 구현이 가능하다.

소스코드

코드 자체는 그리 어려운 부분이 없으므로 따로 설명이 필요할 것이 없다. 기능 자체가 워낙 간단해서인가? 여러분들은 그저 중간에 간단히 적힌 주석 부분만 참고하면 될 것이다. 컴파일을 하고 실행을 하면 화면에서는 나타나는 것이 없지만 실제로 파일이 전송된다. 여러분도 적절히 수정을 하여 원하는 파일들을 서버로부터 전송 받을 수 있을 것이다.
import java.io.*;

import com.oroinc.net.ftp.*;
import com.oroinc.net.*;

public class MyFtpClient {
    static String server = "xxxxx";
    static int port = 21;
    static String id = "xxxxx";
    static String password = "xxxxx";
    FTPClient ftpClient;

    public MyFtpClient(String server, int port, String id, String password) {
        this.server = server;
        this.port = port;
        ftpClient = new FTPClient();
    }

    public static void main(String args[]) {
        MyFtpClient ftp = new MyFtpClient(server, port, id, password);
        ftp.connect();
        ftp.login(ftp.id, ftp.password);
        // 로그파일이 있는 디렉토리로 이동한다
        ftp.cd("/home/ems/emsprj/project/wos/WosLog/log");
        FTPFile[] files = ftp.list();
        for (int i = 0; i < files.length ; i++) {
            String fileName = files[i].getName();
            // 파일 이름에서 확장자만 추출
            String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
            long size = files[i].getSize();
            // 파일 사이즈가 0보다 크고 로그 파일만 가져온다
            if ( (size > 0) && (extension.equalsIgnoreCase("log")) ) {
                File file = ftp.get(fileName, fileName);
            }
        }
        ftp.logout();
        ftp.disconnect();
        System.exit(1);
    }

    // 계정과 패스워드로 로그인
    public boolean login(String user, String password) {
        try {
            this.connect();
            return ftpClient.login(user, password);
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return false;
    }

    // 서버로부터 로그아웃
    private boolean logout() {
        try {
            return ftpClient.logout();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return false;
    }

    // 서버로 연결
    public void connect() {
        try {
            ftpClient.connect(server, port);
            int reply;
            // 연결 시도후, 성공했는지 응답 코드 확인
            reply = ftpClient.getReplyCode();
            if(!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                System.err.println("서버로부터 연결을 거부당했습니다");
                System.exit(1);
            }
        }
        catch (IOException ioe) {
            if(ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch(IOException f) {
                    //
                }
            }
            System.err.println("서버에 연결할 수 없습니다");
            System.exit(1);
        }
    }

    // FTP의 ls 명령, 모든 파일 리스트를 가져온다
    public FTPFile[] list() {
        FTPFile[] files = null;
        try {
            files = this.ftpClient.listFiles();
            return files;
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return null;
    }

    // 파일을 전송 받는다
    public File get(String source, String target) {
        OutputStream output = null;
        try {
            File local = new File(source);
            output = new FileOutputStream(local);
        }
        catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        }
        File file = new File(source);
        try {
            if (ftpClient.retrieveFile(source, output)) {
                return file;
            }
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return null;
    }

    // 서버 디렉토리 이동
    public void cd(String path) {
        try {
            ftpClient.changeWorkingDirectory(path);
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    // 서버로부터 연결을 닫는다
    private void disconnect() {
        try {
            ftpClient.disconnect();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

}
참고문헌

Posted by 티엘로

JavaSound API 는 자바 플랫폼에서 audio 재생을 지원하기 위해 만들어졌다.
이 API는 J2SE 1.3 버전에서 처음 추가되었고, wav, au, aiff, midi 오디오 포멧만을 지원한
다.

mp3 나 ogg 파일 포멧을 사용하고 싶을때는 어떻게 해야 할까?
이러한 문제점을 해결하기 위해 JavaSound API  에서는 JavaSound Service Provider Interfaces (SPIs) 를 이용한 확장을 지원한다. 이 인터페이스를 통해서, 사용자가 구현하고자 하는 오디오포멧을 지원하면 된다.

이것은  JDBC와 같은 개념이다. DB서버가 각각 다르더라도, JDBC 인터페이스를 통해 통일된 DB프로그래밍을 할수 있는 것과 같은 개념이다.

JavaZoom 의 mp3 플러인
* 특징
- mp3 재생만 지원 (MPEG 1, 2 and 2.5, Layers 1, 2, and 3)
- 현재는 mp3 재생만 지원 (Encoding, Converter, Write 기능은 아직 구현되지 않음)
- 메타데이타 ID3 태그 지원 (artist, album, date, copyright, comments, 정보를 뽑아올수 있다)

mp3 를 파일에서 정보를 뽑아오는 방법
1. File 객체를 이용하여 AudioFileFormat 객체를 생성한다.
2. getFormat() 객체를 호출한다.
3. AudioFormat 인스턴스에서 값을 뽑아온다.

File file = new File("filename.mp3");
AudioFileFormat baseFileFormat = null;
AudioFormat baseFormat = null;
baseFileFormat = AudioSystem.getAudioFileFormat(file);
baseFormat = baseFileFormat.getFormat();
AudioFileFormat.Type type = baseFileFormat.getType();
float frequency = baseFormat.getSampleRate();

To play MP3, you need first to call AudioSystem.getAudioInputStream(file) to get an AudioInputStream from an MP3 file, select the target format (i.e., PCM) according to input MP3 channels and sampling rate, and finally get an AudioInputStream with the target format. If JavaSound doesn't find a matching SPI implementation supporting the MP3-to-PCM conversion, then it will throw an exception.

File file = new File("filename.mp3");
AudioInputStream in= AudioSystem.getAudioInputStream(file);
AudioInputStream din = null;
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(
 AudioFormat.Encoding.PCM_SIGNED, 
 baseFormat.getSampleRate(), 
 16,
 baseFormat.getChannels(), 
 baseFormat.getChannels() * 2,
 baseFormat.getSampleRate(),
 false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
// Play now.
rawplay(decodedFormat, din);
in.close();

Second, you have to send the decoded PCM data to a SourceDataLine. This means you have to load PCM data from the decoded AudioInputStream into the SourceDataLine buffer until the end of file is reached. JavaSound will send this data to the sound card. Once the file is exhausted, the line resources must be closed.

private void rawplay(AudioFormat targetFormat, AudioInputStream din)  throws IOException, LineUnavailableException {
 byte[] data = new byte[4096];
 SourceDataLine line = getLine(targetFormat);
 if (line != null) {
 // Start
 line.start();
 int nBytesRead = 0, nBytesWritten = 0;
 while (nBytesRead != -1) {
 nBytesRead = din.read(data, 0, data.length);
 if (nBytesRead != -1) nBytesWritten = line.write(data, 0, nBytesRead);
 }
 // Stop
 line.drain();
 line.stop();
 line.close();
 din.close();
 }
}

private SourceDataLine getLine(AudioFormat audioFormat)
 throws LineUnavailableException {
 SourceDataLine res = null;
 DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
 res = (SourceDataLine) AudioSystem.getLine(info);
 res.open(audioFormat);
 return res;
}


If you're familiar with JavaSound API, you will notice that source code for playing MP3 is similar to the what you'd use to play a WAV file. The source code sample above has no dependencies upon the MP3 SPI implementation. It's transparent for the developer.

Notice that if the file to play was stored on a web server, we would have used:
URL url = new URL(http://www.myserver.com/filename.mp3); AudioInputStream in= AudioSystem.getAudioInputStream(url);

instead of:
File file = new File("filename.mp3"); AudioInputStream in= AudioSystem.getAudioInputStream(file);

Metadata
Most audio formats include metadata such as title, album, comments, compression quality, encoding, and copyright. ID3 tags, used for MP3, are the best-known metadata format. Depending on ID3 version (v1 or v2), they can be found either at the end or at the beginning of an MP3 file. They include information such as duration, title, album, artist, track number, date, genre, copyright, etc. They can even include lyrics and pictures. The famous (and free) SHOUTcast streaming MP3 server, from Nullsoft, uses a different scheme in order to provide additional metadata such as title streaming, which allows a player to display the current song being played from the online radio stream. All of these metadata items need to be parsed and exposed through the SPI implementation. As of J2SE 1.5, the JavaSound API standardizes the passing of metadata parameters through an immutable java.util.Map:

File file = new File("filename.mp3");
AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file);
Map properties = baseFileFormat.properties();
String key_author = "author";
String author = (String) properties.get(key_author);
String key_duration = "duration";
Long duration = (Long) properties.get(key_duration);

All metadata keys and types should be provided in the SPI documentation. However, common properties include:
"duration" (Long): Playback duration of file, in microseconds
"author" (String): Name of the author of the file
"title" (String): Title of the file
"copyright" (String): Copyright message
"comment" (String): Arbitrary text

Using Multiple SPIs in an Application
Adding MP3 audio capabilities to the Java platform means adding JAR files containing the MP3 SPI implementation to the runtime CLASSPATH. Adding Ogg Vorbis, Speex, Flac, or Monkey's Audio support would be similar, but could generate conflicts that make other SPI implementations fail. The following situation could occur:

Your runtime application CLASSPATH includes both MP3 and Ogg Vorbis SPIs.
Your application tries to play an MP3 file.
JavaSound's AudioSystem tries Ogg Vorbis SPI first.
The Ogg Vorbis SPI implementation doesn't detect that incoming file isn't an Ogg-Vorbis-compliant stream, so it doesn't throw any exception.
Your application tries to play an MP3 with the Ogg Vorbis SPI. At best you will get a runtime exception (NullPointerException, ArrayIndexOutOfBoundException), and in the worst case, you will hear weird noises or just deadlock.
In the example above, it's true that the problem comes from the Ogg Vorbis SPI implementation, but it's not easy for the SPI provider to have reliable controls (just think about streaming). Thus, each SPI provider has to pay attention to the others. That's the main practical drawback of the JavaSound plugin architecture. So don't be surprised if you have problems making multiple SPIs work together in your application.

Differences with JMF
JMF stands for Java Media Framework. It's an optional J2SE packages that adds multimedia support to the Java platform. It includes audio (GSM, QuickTime, etc.), video (AVI, QuickTime, H.263, etc.) and RTP streaming features. JMF provides a plugin architecture, but it is not compliant with that of JavaSound. In fact, MP3 support was previously included in JMF, but it was removed in 2002 because of licensing issues.

Conclusion
JavaSound rocks. It provides a plugin architecture allowing any third-party provider to add custom audio format support, such as for MP3 files. API is flexible enough to plug most heterogeneous (lossy, lossless) audio formats, whatever their parameters and metadata, to the Java platform -- "Write once, play anywhere."

References and Resources

JLayer: Java library for decoding and converting MP3 files
MP3 SPI: MP3 plugin for the Java platform
Speex SPI: Speex plugin for the Java platform
Ogg Vorbis SPI: Ogg Vorbis plugin for the Java platform
Monkey's Audio SPI: Monkey's Audio plugin for the Java platform
Flac SPI: Flac plugin for the Java platform
SHOUTcast: SHOUTcast streaming MP3 server
jlGui player: Music player for the Java platform -- a WinAmp clone
JavaSound: SUN homepage
Tritonus: Tritonus project
MP3 Tech: MP3 frame header info
ID3: ID3 definition
The JavaZOOM Team are the authors of the open source projects JLayer and jlGui.


<출처: http://zyint.tistory.com/1 >
Posted by 티엘로

1.    오버라이딩 (overriding)

 

-          상속관계에 있는 클래스들간에 같은 이름의 메소드를 정의하는 행위로 처음 메소드의 기능을 덮어버리는 것

-          , 상위클래스의 있는 메소드의 내용을 하위클래스에서 바꿈

-          기존 클래스의 메소드 구현 부분만 약간 변화시켜 새로운 클래스를 생성할 수 있다.

-          Name, Return type, Argument list가 같아야 한다.

 

2.    오버라이딩 조건

 

-          final로 선언된 메소드는 오버라이딩(중복정의) 할 수 없다.

-          static 메소드는 반드시 static 메소드로 오버라이딩 해야 한다.

-          오버라이딩된 메소드의 접근변경자가 더 private하면 안 된다.

è     새로 오버라이딩 한 메소드는 아래의 접근변경자에서 우측 방향에 있는  또는 같은 종류의 접근변경자만 지정할 수 있다는 것이다.

è     private --> (friendly) --> protected --> public

class A { void m(int i, String s) {} // 메소드 정의 }

class B extends A { private void m(int i, String s) {} }

// friendly private로 중복정의 불가

-          오버라이딩된 메소드가 상위클래스의 메소드보다 더 넓은 범위의 확인 예외(checked exception)를 발생시키면 안 된다.

 

3.    오버라이딩 예제

 

public class Parent4{

   public void restDay(){

       System.out.println("잠을 잔다.");

   }

}

 

public class Child4 extends Parent4{

   public void restDay(){

       System.out.println("데이트를 한다.");

   }

}

 

public class Overriding_Test2{

 public static void main(String args[]){

  Parent4 p=new Parent4();

  Child4 c=new Child4();

  p.restDay();

  c.restDay();

 }

 }

 

실행결과

---------- java ----------

잠을 잔다.

데이트를 한다.

Normal Termination

출력 완료 (0초 경과).

Posted by 티엘로


java 이클립스 설치파일에 덮어씌우면 됩니다.
한글 버젼으로 에러를 잡을 수 있기때문에 디버깅이 편합니다.
초보자들에게는 어쩌면 독이 될수 있기 때문에
자바 공부는 게을리 하면 안되겠죠?

사용자 삽입 이미지

Posted by 티엘로

아래의 코드를 가지고 실행가능한 JAR 파일을 만든다고 가정합니다.

public class HelloApp {

 private String name = "";
 public HelloApp(String name) {
 this.name = name;
}

public void sayHello() {
 System.out.println("Hello, my name is " + name + ".");
 }

 public static void main(String[] args) {
  HelloApp app;
  if (args.length > 0)
   app = new HelloApp(args[0]);
  else
   app = new HelloApp("RESISA~");
  app.sayHello();
 }
}

아래와 같은 방법으로 만들면 됩니다 (Step by Step)

1. Compile:
Prompt> javac HelloApp.java

2. Make a menifest file "MANIFEST.MF".
Prompt> mkdir META-INF
Prompt> edit META-INF\MANIFEST.MF

[Remark]
MENIFEST.MF must contain at least the following line.
Main-Class: HelloApp

3. Create a jar file "hello.jar" by using such a command
jar cmf {manifest file} {jar file} {class files}
Prompt> jar cmf "META-INF\MANIFEST.MF" hello.jar HelloApp.class

4. Execute:
Prompt> java -jar hello.jar
Prompt> java -jar hello.jar "Duke Java!"

Posted by 티엘로
JAVA 콘솔 에서 입력

1. J2SE 1.5 버전이면 java.util.Scanner 클래스   API를 참고

ex) Scanner
       System.out.print("입력값:");
       Scanner  scan  =  new  Scanner (System.in);
       String  testStr = scan.next();

좀더 자세한 사항은 API 뒤져보세요.. API 문서 활용을 생활화 합시다

2. 대부분 많이 사용하는  java.io.BufferedReader

ex) BufferedReader
      
System.out.print("입력하세요: ");
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       String testStr = br.readLine();

3. 이 외에도 한글자만 받아들이는 방법으론
     char c = (char)System.in.read();  //0~255 사이의 아스키코드 한글자

이외의 JAVA 입력에 관한 정보는 위의글 작성자 원문을 참조 하시기 바랍니다
(원문 :
http://www.pmguda.com)
Posted by 티엘로