September 9, 2006

RPM API Pada Java Dengan JNI

Posted in Java, komputer pada 3:55 am oleh fuad

Sebelum membahas lebih lanjut, saya akan memberi perkenalan singkat apa itu JNI. JNI adalah kependekan dari Java Native Interface. Dengan JNI, kelas kelas di Java bisa memanggil prosedur/method yang dibuat dengan menggunakan C/C++ dan sebaliknya program yang kita buat dengan C/C++ bisa menggunakan kelas kelas yang dibuat dengan Java.
Pada Tutorial ini saya akan membahas bagaimana membuat program Java yang mencetak ke konsole dependency dari suatu paket RPM yang telah terinstall sebelumnya.

Catatan:

Tutorial ini dibuat dan dicoba pada sistem operasi linux, dengan Java terinstall pada /usr/java/jdk1.5.0_06/ dan direktori kerja pada /home/fuad/java/JNI

Langkah 1:
Ketiklah kode di bawah ini dan simpan pada file dengan nama RpmProject.java:

public class RpmProject {
public native static Object[] getDependencies();

static{
System.loadLibrary(“RpmProject”);
}
public static void main(String[] args) {
Object [] str=RpmProject.getDependencies();
for(int i=0; i<str.length; i++)
System.out.println(str[i]);
}

}

metode getDescriptionAndDependencies() adalah metode yang akan diimplementasikan dengan cara native dengan menggunakan C/C++. Untuk memberitahu ini pada kompiler maka kita memberinya keyword native.

static{
System.loadLibrary(“RpmProject”);
}

kode di atas digunakan untuk memuat(menload) library yang bernama(“libRpmProject”, perhatikan library yang dimuat adalah libRpmProject.so/.dll bukan RpmProject.so/.dll) Library yang dimuat adalah library yang berisi implementasi dari method native, dalam tutorial ini adalah method getDescriptionAndDependencies().

Langkah 2:
Kompile kelas di atas
[fuad@fuad JNI]$ javac RpmProject.java

Selanjutnya buat file header kelas di atas dengan
[fuad@fuad JNI]$ gjnih RpmProject, jika menggunakan java GNU atau
[fuad@fuad JNI]$ javah RpmProject, jika menggunakan Java Sun.
Hal yang perlu diperhatikan di sini adalah yang menjadi parameter adalah class pada java(tidak berekstensi) bukan kode sumber(*.java).
langkah di atas akan menghasilkan header “RpmProject.h”.

Langkah 3:
Buka file “RpmProject.h” tambahkan variabel pada kedua parameter, dengan nama terserah anda.
file awal “RpmProject.h” :
/* DO NOT EDIT THIS FILE – it is machine generated */
#include <jni.h>
/* Header for class RpmProject */

#ifndef _Included_RpmProject
#define _Included_RpmProject
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: RpmProject
* Method: getDescriptionAndDependencies
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

file “RpmProject.h” setelah diedit:

/* DO NOT EDIT THIS FILE – it is machine generated */
#include <jni.h>
/* Header for class RpmProject */

#ifndef _Included_RpmProject
#define _Included_RpmProject
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: RpmProject
* Method: getDescriptionAndDependencies
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies
(JNIEnv *env, jclass cl);

#ifdef __cplusplus
}
#endif
#endif
Langkah 4:
Buat implementasi dari file header di atas dengan nama RpmProject.c#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmds.h>

#include “RpmProject.h”
JNIEXPORT jobjectArray JNICALL Java_RpmProject_getDependencies (JNIEnv *env, jclass cl){
rpmdb * pdb;
rpmReadConfigFiles(NULL,NULL);
printf(“Config files read \n”);

int dbStatus = rpmdbOpen(“”, &pdb, O_RDONLY, 0644);

if (dbStatus) {
// error opening
printf(“Error on opening RPM Database: (%d) %s\n”, rpmErrorCode(), rpmErrorString());
} else {
printf(“RPM Database opened!\n”);
}

rpmdbMatchIterator mi = rpmdbInitIterator(pdb, RPMDBI_PACKAGES, NULL, 0);
rpmdbSetIteratorRE(mi,RPMTAG_NAME, RPMMIRE_DEFAULT, “gstreamer”);
printf(“Iterator initialized!\n”);
Header header;
int i;
jobjectArray array;
while (header = rpmdbNextIterator(mi)) {
rpmds Rpmds=rpmdsNew(header, RPMTAG_REQUIRENAME , (RPMSENSE_EQUAL|RPMSENSE_LESS));
jstring kal=(*env)->FindClass(env,”java/lang/String”);
array = (*env)->NewObjectArray(env,rpmdsCount(Rpmds),kal,NULL);
for(i=0; i<rpmdsCount(Rpmds); i++){
rpmdsNext(Rpmds);
(*env)->SetObjectArrayElement(env, array, i, (*env)->NewStringUTF(env,rpmdsN(Rpmds)));
}
rpmdsFree(Rpmds);

}

rpmdbFreeIterator(mi);
printf(“Iterator Finished!\n”);
rpmdbClose(pdb);
printf(“RPM Database closed!\n”);

return array;

}

Penjelasan

rpmReadConfigFiles(NULL,NULL);, berfungsi membaca konfigurasi dari database rpm yang ada pada sebuah sistem/komputer. kode ini wajib adanya.

int dbStatus = rpmdbOpen(“”, &pdb, O_RDONLY, 0644); berfungsi membuka database RPM

rpmdbMatchIterator mi = rpmdbInitIterator(pdb, RPMDBI_PACKAGES, NULL, 0); berfungsi mengambil semua paket/software yang ada pada database.

rpmdbSetIteratorRE(mi,RPMTAG_NAME, RPMMIRE_DEFAULT, “gstreamer”); berfungsi memfilter/menyaring paket yang telah dimuat tadi berdasarkan nama paket(RPMTAG_NAME). Nama paket yang digunakan di sini adalah “gstreamer”.

jobjectArray array; adalah variabel khsusus pada JNI. untuk komunikasi antara Java dengan C/C++ digunakan suatu variabel khusus (http://java.sun.com/developer/onlineTraining/Programming/JDCBook/index.html). Karena pada metode getDependencies pada kelas Java tadi meminta mengembalikan nilai yag bertipe array objek, maka nilai yang dikembalikan pada fungsi ini harus variabel JNI yang bertipe jobjectArray.

rpmds Rpmds=rpmdsNew(header, RPMTAG_REQUIRENAME , (RPMSENSE_EQUAL|RPMSENSE_LESS));
Kode di atas mengambil semua dependency dari sebuah paker berdasarkan nilai headernya

jstring kal=(*env)->FindClass(env,”java/lang/String”);
Memanggil kelas pada java yang akan digunakan pada pengembalian nilai nanti.

array = (*env)->NewObjectArray(env,rpmdsCount(Rpmds),kal,NULL);
Membuat array objek baru yang berisi string(sesuai tipe variabel “kal”) dengan panjang sebanyak rpmdsCount(Rpmds)

for(i=0; i<rpmdsCount(Rpmds); i++){
rpmdsNext(Rpmds);
(*env)->SetObjectArrayElement(env, array, i, (*env)->NewStringUTF(env,rpmdsN(Rpmds)));
}

Untuk setiap dependency yang dimuat akan dimasukkan ke dalam variabel array pada indeks i.

Langkah 5:

Kompile file di atas
[fuad@fuad JNI]$ gcc -c -fPIC -I/usr/java/jdk1.5.0_06/include/ -I/usr/java/jdk1.5.0_06/include/linux/ RpmProject.c
hasil dari kompilasi di atas adalah file RpmProject.o

Selanjutnya buat library libRpmProject.so dengan cara
[fuad@fuad JNI]$ gcc -shared -o libRpmProject.so RpmProject.o -lrpm -lrpmdb
hasil dari kompilasi di atas adalah file libRpmProject.so

Langkah 6:

Setelah kelima langkah di atas berhasil maka kelas java “RpmProject” sudah bisa dijalankan
[fuad@fuad JNI]$ java RpmProject

jika saat menjalankan anda mendapatkan error:
Exception in thread “main” java.lang.UnsatisfiedLinkError: no RpmProject in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:992)
at RpmProject.<clinit>(RpmProject.java:10)
maka anda harus terlebih dahulu mengeset variabel LD_LIBRARY_PATH yang menunjuk file libRpmProject.so.
[fuad@fuad JNI]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/fuad/java/JNI/

4 Komentar »

  1. dito said,

    mas, saya mau tanya,
    Bila kita ingin menulis isi suatu directory di linux dimana isi nya berupa isi dari folder lain bisa tidak??? jadi semacam shortcut begitu.

    apa hal itu bisa dilakukan, atau harus menggunakan API??
    kalau bisa jawabn ikirim ke email saya mas
    sekian terima kasih

  2. fuad said,

    Saya kurang mengerti maksud anda?
    Bisa lebih spesifik g?

  3. eldian herlana said,

    mas saya mo nanya kode API itu apa maksudnya, sebelumnya kode API itu muncul di WordPress Saya,,tlng kasih tau juga kegunaaanya, thanks be4 atas balasannya.,,,

  4. fuad said,

    API itu kependekan dari Application Programming Interface. Fungsi fungsi untuk mengembangkan atau modifikasi suatu perangkat lunak. APi pada wordpress biasanya digunakan untuk mengembangkan/membuat plugin


Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: