
QRCodes are two dimensional barcodes that can be decoded (scanned) at high speed. QrCode is created by Japanese corporation Denso-Wave. These two dimentisional bar codes are very common in Japan. They are widely used in ad sector.
URLs, Text, Phone numbers can be encoded in these codes. There are J2ME applications that can decode QRCodes. If you have a java enabled cell phone with a camera, install the application from http://reader.kaywa.com/ and begin scanning QRCodes.
I am going to list what can be done with a QRCode reader and a QRCode generator later in this blog.
The image in this post is an example of generated QR Code. Guess what is encoded in the picture. Install the QRCode reader and scan the image ;)
Wednesday, February 27, 2008
QRCodes are becoming popular
Sunday, February 3, 2008
RESTFUL URLs with Stripes
I have developed several web applications with Struts and Spring MVC. The main difference between Stripes and other MVC frameworks is the configuration. Struts uses struts-config.xml to configure its action classes and its action forms. Stripes requires minimal configuration to get up and running (dispatcher conf. in web.xml), and zero configuration per ActionBean or page. If you have never heard of Stripes, go read Quick Start Guide, you will thank to me ;). I do not want to duplicate documentation in this post, because Stripes team has prepared a good and comprehensive documentation.
In this post I will explain how you can create clean urls with Stripes. Stripes does not need a configuration file to configure its action beans. If you does not supply any additional configuration Stripes configures your web application with the default RuntimeConfiguration class. An ActionResolver is responsible for finding your action beans and mapping HTTP requests to action bean methods. Stipes uses NameBasedActionResolver by default.
As it is explained here the default behaviour of NameBasedActionResolver is as follows:
- All classes that implements the ActionBean interface is searched. (By default Stripes searches for ActionBean implementations in classpath. But you can narrow the scope of this search by changing the default configuration. This will improve startup performance of your application. See ActionResolver Properties)
- Packages "web, www, stripes, action" and their parents are removed. For example "com.companyname.superproject.web.user.DetailsActionBean" becomes "user.DetailsActionBean".
- Action or ActionBean suffix is trimmed. "user.DetailsAactionBean" becomes "user.Details"
- "." is replaced with "/". "user.Details" becomes "/user/Details"
- Finally NameBasedActionResolver appends ".action" to the end of the action URL and we get "/user/Details.action"
If you want to use clear URLs like "http://www.mysite.com/user/details/12345" instead of "http://www.mysite.com/user/Details.action?userid=12345" you must write your custom ActionResolver implementation. Don't worry it is very easy. First in your web.xml tell Stripes to use your ActionResolver class:
web.xml
<filter>
<display-name>Stripes Filter</display-name>
<filter-name>StripesFilter</filter-name>
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
<init-param>
<param-name>ActionResolver.UrlFilters</param-name>
<param-value>/WEB-INF/classes</param-value>
</init-param>
<init-param>
<param-name>ActionResolver.Class</param-name>
<param-value>com.companyname.superproject.RestfulActionResolver</param-value>
</init-param>
</filter>
Then write a class that extends NameBasedActionResolver. You only need to override getBindingSuffix() and getUrlBinding(String s) methods. An implementaion (RestfulActionResolver.java) is listed below:
RestfulActionResolver.java
package com.companyname.superproject.RestfulActionResolver
import net.sourceforge.stripes.controller.NameBasedActionResolver;
import org.apache.log4j.Logger;
public class RestfulActionResolver extends NameBasedActionResolver {
@Override
protected String getBindingSuffix() {
return "";
}
@Override
protected String getUrlBinding(String s) {
String urlBinding = super.getUrlBinding(s);
return urlBinding.toLowerCase();
}
}
RestfulActionResolver finds ActionBean instances and performs HTTP requests bindings for you.
"com.companyname.superproject.web.user.DetailsActionBean" action bean is mapped to URL "/user/details".
I used Stripes version 1.4.3 in the above example.
I hope you enjoy the post.
Tuesday, January 29, 2008
Extended desktop configuration with xrandr
We will use xrandr utility to configure multiple screens. Before using xrandr you must check xorg.conf file ( /etc/X11/xorg.conf )
Section "Screen"
Identifier "Default Screen"
Device "Intel Corporation 82852/855GM Integrated Graphics Device"
Monitor "Generic Monitor"
Defaultdepth 24
SubSection "Display"
Depth 24
Virtual 2304 1792
Modes "1280x1024@75" "1024x768@60"
EndSubSection
EndSection
The Virtual keyword is important. Sum of resolution widths and sum of resolution heights of two monitors are written in Virtual.
For example : 1280 + 1024 = 2304 and 1024 + 768 = 1792
You must restart X server after updating xorg.conf file. ctrl-alt-backspace is the shortcut to restart X. After successfully restarting X server, run the following commands:
First command sets VGA (19'' LCD monitor) resolution to 1280x1024. Second command sets laptop monitor resolution to 1024x768. The last command places the extended monitor (VGA) right of laptop monitor. That's it. At least it works for me.
xrandr --output VGA --mode 1280x1024
xrandr --output LVDS --mode 1024x768
xrandr --output VGA --right-of LVDS
For more information check intellinuxgraphics.org site.
Sunday, January 27, 2008
How to change GNOME desktop wallpaper programmatically
gconftool-2 -R /desktop/gnomecommand displays all the preferences listed under "/desktop/gnome" repository. You can print the value of a key in the gnome preferences table with the "g" parameter.
The "R" option prints all subdirectories and entries under a directory, recursively.
ilkinulas@tututil:~/bin$ gconftool-2 -g /desktop/gnome/screen/default/0/resolution
1280x1024
You can set a key to a value with the option "s". When you set a gnome preference, applications that are interested in that preference will be notified. For example:
ilkinulas@tututil:~$ gconftool-2 -R /desktop/gnome/background
color_shading_type = solid
secondary_color = #dadab0b08282
primary_color = #000000000000
picture_filename = /home/ilkinulas/Pictures/wallpaper/w1209.jpg
picture_options = scaled
picture_opacity = 100
draw_background = true
ilkinulas@tututil:~$ gconftool-2 -g /desktop/gnome/background/picture_filename
/home/ilkinulas/Pictures/wallpaper/w1209.jpg
sets gnome desktop background picture to "/home/ilkinulas/Pictures/wallpaper/64269-1.png". The option "-t" is used to specify the type of the value of the key. If you execute the command above you will see that your desktop wallpaper is changed. Now lets write a shell script to randomly select a picture and set selected picture as wallpaper.
gconftool-2 -t str -s /desktop/gnome/background/picture_filename "/home/ilkinulas/Pictures/wallpaper/64269-1.png"
#!/bin/bash
DIR=/home/ilkinulas/Pictures/wallpaper
counter=0;
for i in `find $DIR -iname *.jpg -o -iname *.png -o -iname *.gif`
do
pictures[$counter]=$i;
counter=$counter+1;
done
index=$((RANDOM%${#pictures[*]}));
gconftool-2 -t str --set /desktop/gnome/background/picture_filename ${pictures[$index]};
If you do not want to execute the above script manually you can add a new crontab entry. I start working in the office at 8 am and I use "00 09 * * *" as my crontab schedule, I want my wallpaper change everyday at 9 am, if my computer is on ;)
If the way I explain in this post is too complicated you can try Webilder. Webilder delivers stunning wallpapers to your Linux desktop, directly from Flickr and Webshots. You choose what keywords (tags) to watch for, and photos are automatically downloaded to your computer. Webilder can also change the wallpaper every few minutes.
Saturday, January 26, 2008
ReadWriteLock example in Java
In Java synchronized keyword is used to acquire a exclusive lock on an object. When a thread acquires a lock of an object either for reading or writing, other threads must wait until the lock on that object is released. Think of a scenerio that there are many reader threads that reads a shared data frequently and only one writer thread that updates shared data. It's not necessary to exclusively lock access to shared data while reading because multiple read operations can be done in parallel unless there is a write operation.
In this post i'll give an example usage of ReadWriteLock interface which is introduced in the Java 1.5 API Doc. In Java Api Documentation it says :
A ReadWriteLock maintains a pair of associated locks,
one for read-only operations and one for writing.
The read lock may be held simultaneously by multiple reader threads,
so long as there are no writers. The write lock is exclusive.
Reader threads can read shared data simultaneously. A read operation does not block other read operations. This is the case when you execute an SQL SELECT statement. But write operation is exclusive. This means all readers and other writers are blocked when a writer thread holds the lock for modifing shared data.
Writer.java This class represents a thread that updates shared data. Writer uses WriteLock of ReadWriteLock to exclusively lock access to dictionary.
01 package deneme.readwritelock;
02
03
04 public class Writer extends Thread{
05 private boolean runForestRun = true;
06 private Dictionary dictionary = null;
07
08 public Writer(Dictionary d, String threadName) {
09 this.dictionary = d;
10 this.setName(threadName);
11 }
12 @Override
13 public void run() {
14 while (this.runForestRun) {
15 String [] keys = dictionary.getKeys();
16 for (String key : keys) {
17 String newValue = getNewValueFromDatastore(key);
18 //updating dictionary with WRITE LOCK
19 dictionary.set(key, newValue);
20 }
21
22 //update every seconds
23 try {
24 Thread.sleep(1000);
25 } catch (InterruptedException e) {
26 e.printStackTrace();
27 }
28 }
29 }
30 public void stopWriter(){
31 this.runForestRun = false;
32 this.interrupt();
33 }
34 public String getNewValueFromDatastore(String key){
35 //This part is not implemented. Out of scope of this artile
36 return "newValue";
37 }
38 }Reader.java This class represents a thread that reads share data.
01 package deneme.readwritelock;
02
03 public class Reader extends Thread{
04
05 private Dictionary dictionary = null;
06 public Reader(Dictionary d, String threadName) {
07 this.dictionary = d;
08 this.setName(threadName);
09 }
10
11 private boolean runForestRun = true;
12 @Override
13 public void run() {
14 while (runForestRun) {
15 String [] keys = dictionary.getKeys();
16 for (String key : keys) {
17 //reading from dictionary with READ LOCK
18 String value = dictionary.get(key);
19
20 //make what ever you want with the value.
21 System.out.println(key + " : " + value);
22 }
23
24 //update every seconds
25 try {
26 Thread.sleep(1000);
27 } catch (InterruptedException e) {
28 e.printStackTrace();
29 }
30 }
31 }
32
33 public void stopReader(){
34 this.runForestRun = false;
35 this.interrupt();
36 }
37 }Dictionary.java This is a simple and thread safe dictionary. Read operations are managed through ReadLock and write operations (updates) are managed throuh WriteLock.
01 package deneme.readwritelock;
02
03 import java.util.HashMap;
04 import java.util.concurrent.locks.Lock;
05 import java.util.concurrent.locks.ReentrantReadWriteLock;
06
07 public class Dictionary {
08
09 private final ReentrantReadWriteLock readWriteLock =
10 new ReentrantReadWriteLock();
11
12 private final Lock read = readWriteLock.readLock();
13
14 private final Lock write = readWriteLock.writeLock();
15
16 private HashMap<String, String> dictionary = new HashMap<String, String>();
17
18 public void set(String key, String value) {
19 write.lock();
20 try {
21 dictionary.put(key, value);
22 } finally {
23 write.unlock();
24 }
25 }
26
27 public String get(String key) {
28 read.lock();
29 try{
30 return dictionary.get(key);
31 } finally {
32 read.unlock();
33 }
34 }
35
36 public String[] getKeys(){
37 read.lock();
38 try{
39 String keys[] = new String[dictionary.size()];
40 return dictionary.keySet().toArray(keys);
41 } finally {
42 read.unlock();
43 }
44 }
45
46 public static void main(String[] args) {
47 Dictionary dictionary = new Dictionary();
48 dictionary.set("java", "object oriented");
49 dictionary.set("linux", "rulez");
50 Writer writer = new Writer(dictionary, "Mr. Writer");
51 Reader reader1 = new Reader(dictionary ,"Mrs Reader 1");
52 Reader reader2 = new Reader(dictionary ,"Mrs Reader 2");
53 Reader reader3 = new Reader(dictionary ,"Mrs Reader 3");
54 Reader reader4 = new Reader(dictionary ,"Mrs Reader 4");
55 Reader reader5 = new Reader(dictionary ,"Mrs Reader 5");
56 writer.start();
57 reader1.start();
58 reader2.start();
59 reader3.start();
60 reader4.start();
61 reader5.start();
62 }
63
64 }Monday, January 21, 2008
Birkaç vi kısayolu
o : Bulunduğun satırın altına yeni bir satır açar ve yazmaya bu yeni satırdan devam edebilirsin.
w : İleriye doğru kelime kelime ilerler
b : Kelime kelime geriye gider.
cw : İmlecin üzerinde olduğu kelimeyi değiştirmeye yarar.
9G : İmleç 9. satıra gider.
H : İmleç sayfanın en tepesine gider (Birinci satıra değil görünen sayfanın ilk satırına)
L : İmleç sayfanın en altıne gider
~ : İmlecin üzerinde olduğu karakteri büyük harf ise küçük harfe, küçük harf ise büyük harfe çevirir. (case dememek için çektiğimiz sıkıntıya bak ya. Kısaca karakterin case'ini değiştirir)
. : son çalıştırılan komutu çalıştırılır.
c$ :İmlecin bulunduğu yerden satır sonuna kadar siler. Editor INSERT modunda kalır. Yazmaya devam edebiliriz.
mt : Imlecin bulunduğu satırı "t" etiketi ile işaretler 't ile imleç işaretli satıra uçar.
vi editörü ile ilgili daha detaylı türkçe bilgi için belgeler.org adresine bakabilirsiniz.
Friday, January 18, 2008
Başkaldıran dosya sistemlerini fuser ile hizaya getirin
Dosya sistemindeki bir dosyayı ya da bir soketi hangi
process'in kullandığını gösteren komut.
"Tamam da ne işime yarayacak dosyayı hangi process'in kullandığını öğrenmek" diyenler için de fuser kullanımı ile ilgili bir örnek verelim. Yeni yazdığınız bir CD'yi CD sürücünüze takıp mount ettiniz. CD içindeki dokumanlarla işiniz bittikten sonra CD'yi çıkartmaya çalıştığınızda aşağıdaki gibi bir mesajla karşılaşabilirsiniz:
Ya da komut satırında umount komutu ile CD'yi unmount etmek isteğinizde aşağıdaki gibi "device is busy" mesajı ile karşılaşabilirsiniz.
İşte fuser tam burada yardıma koşuyor. CD'yi meşgul eden process'in PID'sini bulmak için aşağıdaki işlemler yapılır.
Bizim örneğimizde aranan process 7614 numaralı evince dir.(Gnome Document Viewer) Bu process'i kapattıktan sonra CD yi problemsiz unmount edebiliriz.
