20051114 星期一 2005年11月14日

Time to say goodbye

If you are still interested in what I posted, please access http://mengyan.org/english/.

Farewell, my friends. Good luck, Sun.

( 2005年11月14日, 06:02:40 下午 GMT+08:00 ) Permalink
20050809 星期二 2005年08月09日

Scripting for Java

JSR223 "describe mechanisms allowing scripting language programs to access information developed in the Java Platform and allowing scripting language pages to be used in Java Server-side Applications."

This defines a framework to allow scripting language programs to access information developed in the Java platform. We currently plan to integrate this into Mustang for b40. Aside from the framework, we will also include a JavaScript engine based on the Mozilla Rhino implementation. Later, we hope to include a scripting shell that is script language independent. This will be a very cool way to create a prototype, do some exploratory coding, and learn new APIs.

The latest release of Mustang has already included this feature. You can check out the latest release of JavaSE to have a try.

There are 3 blog entries to talk about this:

Example: using JavaScript in Java

Simple JavaScripting from Java

Scripting Support in Mustang - An Example You Can Try

Then why adding scripting languages to Java?

two ways of using Java aware scripting languages: exploratory programming and testing, and user level scripting of applications. - Scripting Languages For Java

What interested me most is that it is a framework but not a simple implementation. So, any other scripting languages (such as PHP, Ruby ... )can be added to Java if someone develop a module implementation following the framework standard. So, it's "An architecture of participation".

//import package
import javax.script.*;

public class Main {
    public static void main(String[] args) {
        try {
            // create a script engine manager
            ScriptEngineManager manager = new ScriptEngineManager();
            // create script engine for JavaScript
            ScriptEngine jsengine = manager.getEngineByName("js");
            // evaluate JavaScript code from String
            jsengine.eval("print('hello world')");
        } catch (ScriptException se) {
            // Handle script exception here..
            // FIXME: do a better job here!
            se.printStackTrace();
        }
    }
}

( 2005年08月09日, 10:05:18 上午 GMT+08:00 ) Permalink 评论 [1]
20050720 星期三 2005年07月20日

How to implement queue with stack?

How to implement queue with stack?

Interesting topic, right? One of my friends encounter this problem when he's applying software engineer position in a company.

Suppose we have only stack available

Stack* stack_init();
void push(Stack*, int);
int pop(Stack*);
void stack_free();

Please implement the following interface of queue

Queue* queue_init();
void inq(Queue*, int);
int outq(Queue*);
void queue_free();

 

Any idea, buddy? Here come 3 solutions:

1) By Winters Mi


Stack* stack_init();
void push(Stack*, int);
int pop(Stack*);
void stack_free(Stack*);

struct Queue {
 struct Stack* stack_;
}

Queue* queue_init()
{
 Queue* queue = new Queue;
 queue->stack_ = stack_init();
}

void inque(Queue* que, int newvalue)
{
 Stack* temp = stack_init();
 int value;
 while((value = pop(que->stack_) != EOF){
 push(temp, value);
}
push(que->stack_, newvalue);
 while((value = pop(temp)) != EOF){
  push(que->stack_, value);
 }
}

int outque(Queue* que)
{
 pop(que->stack_);
}

void queue_free(Queue* que)
{
 stack_free(que->stack_);
 delete que;
}


So, it's a O(N) solution. 2) By Green Wang


struct Queue
{
 struct Stack *stack_forward;
 struct Stack *stack_backward;
 int iStack;
}

Queue* queue_init()
{
 Queue* que = new Queue;
 que->stack_forward = stack_init();
 que->stack_backward = stack_init();
 que->iStack = 1;
 
 return que;
}

void stack_reverse(Stack *dest, Stack *src)
{
 int value;
 while((value = pop(src) != EOF)
 {
  push(dest, value);
 }
}

void inque(Queue *que, int newvalue)
{
 if (que->iStack != 1)
 {
  stack_reverse(que->stack_forward, que->stack_backward);
  que->iStack = 1;
 }
 
 push(que->stack_forward, newvalue);
}

int outque(Queue *que)
{
 if (que->iStack != -1)
 {
  stack_reverse(que->stack_backward, que->stack_forward);
  que->iStack = -1;
 }
 
 return pop(que->stack_backward)
}

void queue_free(Queue* que)
{
 stack_free(que->stack_forward);
 stack_free(que->stack_backward);
 delete que;
}


If the operation of the queue is consecutive "in" or "out", it's O(1); Or else O(n). This algorithm overcomes the shortcoming of the first one. Because if the operation is consecutive, we don't need to reverse the stack back.

3) By Changzheng Liu


/* create the type Queue by Stack */
typedef struct {
 Stack* stack_out;
 Stack* stack_in;
} Queue;

/* Init Queue */
Queue* queue_init()
{
 Queue* que = (Queue*)malloc(sizeof(Queue));
 que->stack_out = stack_init();
 que->stack_in = stack_init();
 return que;
}

/* reverse the elements from src to dest */
void stack_reverse(Stack *dest, Stack *src)
{
 int value;
 while((value = pop(src) != EOF)
 {
  push(dest, value);
 }
}

/* put element into queue */
void inque(Queue* que, int elem)
{
 /* always push elements into stack_in */
 push(que->stack_in, elem);
}

/* get the element from queue */
int outque(Queue* que)
{
 int ret;
 
 /* always get element from stack_out,
 * if stack_out is empty, reverse stack_in to stack_out and try to pop from stack_out again
 */
 if ((ret = pop(que->stack_out)) == EOF)
 {
  stack_reverse(que->stack_out, que->stack_in);
  ret = pop(que->stack_out);
 }

 return ret;
}

/* free the queue */
void queue_free(Queue* que)
{
 stack_free(que->stack_out);
 stack_free(que->stack_in);
 free(que);
}


Changzheng got these code from Google. :P. It's really good. The idea is very simple, 2 stacks, one for in and one for out. For the "in" operation, just push all into the stack_in. For the "out" operation, if stack_out is empty, reverse the stack_in to stack_out, or else just pop the value.

So for "in" operation O(1); for "out" operation, if stack_out is empty, it's O(n), else O(1).

( 2005年07月20日, 04:54:12 下午 GMT+08:00 ) Permalink 评论 [1]
20050615 星期三 2005年06月15日

Opening Day

As you may have noticed, June 14, 2005 - the OPENING DAY for the OpenSolaris project.

Don't hesitate, check detail informations here:

SUN.com

OpenSolaris.org

And there's so many "OpenSolaris" tags on the planet, check here:

Technorati

del.icio.us

Flickr

( 2005年06月15日, 09:03:42 上午 GMT+08:00 ) Permalink 评论 [1]
20050608 星期三 2005年06月08日

How to get the current directory in java?

A useful tip to share with you.

I need to read the file from the current directory (same directory with the main jar file). In my code, I just use "new File("test")", and it works quite well.

But in my colleague's machine, it throws the FileNotFound exception. Oh, we I saw the exception in his screen, I know that it's a careless fault. The problem is I accessed files in a given location without an absolute path prefix.

In my case:

cd /home/elan/test/
java -jar test.jar

So, the current working directory is "/home/elan/test/", and we can access the file by a relative path.

My colleague's case:

cd /usr/java/bin
java -jar /home/elan/test/test.jar

The working directory is "/usr/java/bin", and no "test" existed in this folder.

Ok, then how to get the current directory?

As we know, System.getProperty("user.dir") will get the working directory and System.getProperty("user.home") will get the home directory ("/home/elan/" for linux and "$:/document and settings/elan/" for windows case), but I cannot get any clue to get the current directory which contains my jar file and the "test" file.

I have thought that I can get this kind of code in "java.io" or "runtime" classes, but I cannot find any clue. So, how about get the location of the jar file since it's the file that in this directory. After a while, I got the answer:

getClass().getProtectionDomain().getCodeSource().getLocation()

It will return the class code base's location, and in my case, the jar file's location. So I just need to get the parent path of this location. The problem solved.

BTW:

1) You'd better pack the file into the jar and use the classloader to read it;

2) Or you can use the home directory ( System.getProperty("user.home") )

3) In my case, for some special reason, I must do this. :P

( 2005年06月08日, 06:29:07 下午 GMT+08:00 ) Permalink 评论 [9]

Apple's shift to Intel-based chips

Just abstract some comments here. To imagine the Mac OS based on Solaris, the good UI experience plus the the world's highest volume and most secure UNIX. :-)

" So I'd like to personally invite you to adopt Solaris 10 as the underpinning of the next generation Mac. We both respect Unix, both respect innovation*, and both clearly see volume opportunities in extending choice to developers. We'd love to work together. " - Jonathan

"Usually there are two players rather than three: the favorite and the underdog. The "third" person does not matter as much. With Apple moving to x86 it can quickly become the underdog of the platform and put Linux in third (outsider) place." - Slashdot

( 2005年06月08日, 11:30:38 上午 GMT+08:00 ) Permalink 评论 [1]
20050606 星期一 2005年06月06日

Share is good

" We began with a simple belief. Sharing is good. Today, Java is shared by 4,500,000 developers and found in hundreds of millions of products – everything from cell phones, PC’s and smart cards, to mobile games and automobile dashboards. Solaris, the world’s most advanced operating system, is shared by a base of over 1,000,000 users. And OpenSolaris ensures more people in more places will soon have more options. "

"On June 1st, we launched a campaign that delivers the stories and success of many Sun customers and partners, along with our simple philosophy, to the world. See the launch ad here. "

Get detailed story here.

( 2005年06月06日, 03:24:39 下午 GMT+08:00 ) Permalink 评论 [1]
20050603 星期五 2005年06月03日

A very good blog about Netbeans

Geertjan just began his blog - Mainly focus on Netbeans, Ant and other related things.

We have chatted some Netbeans problems via email, I found he is really a zestful person.

So, if you are Netbeans funs, you shouldn't miss his blog.

( 2005年06月03日, 10:27:28 上午 GMT+08:00 ) Permalink 评论 [1]
20050509 星期一 2005年05月09日

Burn my feed

I have decided to burn my feed using feedburner's service. Because I wanna to burn my other blogs, my flickr photos, my delicious and furl information to a unique rss feed, so I choose feedburner. I definitely know it's risky, but I think it deserved. :-)
Here's the new feed. Really apologize for the inconvenience.

Update:
Thanks Bryce's comments
" Here's the best argument I've read for shying away from Feedburner:
http://www.cadenhead.org/workbench/comment/2524
FWIW, I do use Feedburner (just to get the Flickr splicing, and my readership is not so large that I really care if my feed goes away tomorrow -- I'm fine asking people to resubscribe if it comes to that..)
-- bryce"
And the link is really a good article to read. Here's my reply :
" Yep, it's just what I worried about. I really love that blog give us a none-centralize world, but feedburner bring us back to the centralize one. But I really need the service they provide:
1) Add a wrapper to my seed, so I can migrate my BSP without bothering my reader; (Abstraction and wrapper is really important in our life ;-) );
2) Aggregate flickr, furl, and it's important to me;
3) They provide detailed statistic;

So, to be or not to be, it's a hard decision " ( 2005年05月09日, 09:50:09 下午 GMT+08:00 ) Permalink 评论 [1]
20050429 星期五 2005年04月29日

"SWT Happens"

"I have been working with Swing intermittently for the last seven years, and with SWT exclusively for the last four months. Under the terms of a new contract, I was required to use SWT to implement the client to a J2EE price tracking system for a major retailer. Before applying for the role, I was told that the organization had already decided that the client would be implemented in Java, and to use SWT instead of Swing. Since my very first contact with the organisation I have been trying to discover the origin of that decision, and the reasoning behind it. To date, I have been unable to discover any rational reason for choosing SWT over its obvious competitor, Swing.“ -- Mr Ed.

Details in http://www.hacknot.info/hacknot/action/showEntry?eid=74 ( 2005年04月29日, 11:34:37 下午 GMT+08:00 ) Permalink 评论 [13]
20050329 星期二 2005年03月29日

Netbeans RCP In Action (2)

How to develop a module using netbeans platform?

I have ever developed a little tool called MP3 Renamer before. Because I have many music files in my laptop, but many of them are called "1.mp3
" , "music.mp3". I build this little tool to parse the tag information from the mp3 files and rename the file name to "Author -- Songname.mp3".

I decide to change the stand alone application to a netbeans module to test the Netbeans RCP. Here I'd like to share my experience with you.

1) What we needed

2) Install the Netbeans RCP

After unzip the netbeans zip file to a directory ("/home/elan/netbeans" in my case), make a user preference directory such as "elan" in the netbeans directory. Then, type "/home/elan/netbeans/platform4/lib/nbexec --userdir /home/elan/elan to test if it works. If it works, congratulations, we have already installed the netbeans RCP and can build our own module base on it.

3) Create MP3 Renamer Module

First, we should build the module working enviroment. Here's the structure of the Mp3 renamer dir:

--build.xml
--manifest.mf
--lib/
--nbproject/
--src/

Source files are all put into "src" and third party library files are put into "lib" directory.

After that, we need to edit the manifest file ("manifest.mf"). The content of mine is :

Manifest-Version: 1.0
OpenIDE-Module: Mp3 Renamer/1
OpenIDE-Module-IDE-Dependencies: IDE/1 > 4.0
OpenIDE-Module-Specification-Version: 1.0
OpenIDE-Module-Layer: com/vvworkshop/shareware/mp3rename/resources/layer.xml
OpenIDE-Module-Localizing-Bundle: com/vvworkshop/shareware/mp3rename/Bundle.properties


The layer file ("com/vvworkshop/shareware/mp3rename/resources/layer.xml") describe the extension point and the Bundle file ("com/vvworkshop/shareware/mp3rename/Bundle.properties") store the localized string of our module.

You can modify the file according to your case.

Ok, let's take a look at the layer file:

<filesystem>
<folder name="Menu">
<folder name="View">
<file name="com-vvworkshop-shareware-mp3rename-Mp3RenamerAction.instance">
</file>
</folder>
</folder>
</filesystem>

It extends the netbeans system menu and will insert our own one into the "View" sub menu. The Action that the menu connected with is "com.vvworkshop.shareware.mp3rename.Mp3RenamerAction". Let's take a look at the source file of this action.

"
public class Mp3RenamerAction extends CallableSystemAction {
// System Component

public Mp3RenamerAction() {
}

public void performAction() {
SiteListComponent.activate();
}

public String getName() {
return NbBundle.getMessage(Mp3RenamerAction.class, "SLC_title");
}

public HelpCtx getHelpCtx() {
return null;
}

protected boolean asynchronous() {
return false;
}
}
"

The most important functions are "performAction" and "getName". Function "getName" will return the menu name, and function "performAction" will provide the real action when the user click the menu. And in the Bundle.properties file, there's one line "SLC_title=MP3 Renamer" , so, the menu name will be called"Mp3 Renamer". "performAction" provides the action, in my case, in this function the MP3 Renamer main panel will dock into the netbeans panel.

Another important file is "build.xml", we can use Ant to compile, archive, and build "nbm" file. The file is a little long, I'd like to abstract some important slice from my ant script:

Some property

"
<property name="nb.home" location="/home/elan/netbeans"/>
<property name="test.user.dir" location="/home/elan/netbeans/elan"/>

<path id="class.path">
<pathelement location="${nb.home}/platform4/core/openide.jar"/>
<pathelement location="${nb.home}/platform4/core/openide-loaders.jar"/>
</path>

<property name="libs" value="${nb.home}/platform4/core/openide.jar;${nb.home}/platform4/core/openide-loaders.jar"/>

<property name="package.dir" value="mp3renamer"/>

<!-- The paths of the clusters to be opened when the platform starts. -->
<!-- Name of our NetBeans cluster. -->
<property name="nbantext.jar" location="lib/nbantext.jar"/>
<property name="cluster.dir" value="mp3renamer"/>
<property name="modules.dir" value="${cluster.dir}/modules"/>
<property name="module.name" value="mp3renamer"/>
<!-- Path to the module XML directory. -->
<property name="modulexml.dir" value="${cluster.dir}/config/Modules"/>

<!-- MakeNBM Ant task needs this. -->
<property name="nb.system.dir" value="config"/>

<path id="cluster.path">
<pathelement location="${nb.home}/${cluster.dir}"/>
</path>

"

How to archive the jar file

besides the archive work, we also need to create the module xml file. And in order to build it, we also need a jar file named as "nbantext.jar", it can be acquired from the NetBeans IDE binary.

"
<target name = "archive" depends = "compile" description = "Build the JAR files" >
<!-- Put everything in ${classes} into a basic archive into $(archive)/MP3Renamer.jar -->
<mkdir dir = "${archive}"/>
<mkdir dir="netbeans/${modules.dir}"/>
<jar destfile= "netbeans/${modules.dir}/${module.name}.jar" manifest="manifest.mf" compress="false">
<fileset dir = "${classes}" excludes="**/*.java"/>
<!--<fileset dir="${source}" excludes="**/*.java" /> -->
</jar>

<mkdir dir="netbeans/${modulexml.dir}"/>
<taskdef name="createmodulexml" classpath="${nbantext.jar}"
classname="org.netbeans.nbbuild.CreateModuleXML"/>
<createmodulexml xmldir="netbeans/${modulexml.dir}">
<enabled dir="netbeans/${cluster.dir}">
<include name="modules/${module.name}.jar"/>
</enabled>
</createmodulexml>
</target>

"

How to create the "nbm" file

"
<target name="nbm" depends="archive"
description="Prepare the module for distribution via Auto Update.">
<taskdef name="makenbm" classpath="${nbantext.jar}"
classname="org.netbeans.nbbuild.MakeNBM"/>
<taskdef name="genlist" classpath="${nbantext.jar}"
classname="org.netbeans.nbbuild.MakeListOfNBM"/>
<!-- Need to generate the update_tracking file for makenbm. -->
<genlist outputfiledir="netbeans/${cluster.dir}"
module="modules/${module.name}.jar">
<fileset dir="netbeans/${cluster.dir}">
<include name="modules/${module.name}.jar"/>
<include name="config/Modules/${module.name}.xml"/>
</fileset>
</genlist>
<makenbm file="${module.name}.nbm" needsrestart="false"
productdir="netbeans/${cluster.dir}"
module="modules/${module.name}.jar"
homepage="http://www.vvworkshop.com"
distribution="http://www.vvworkshop.com"/>
</target>

"

You can just copy this target to your build file and change the propertiy value.

4) Test the Module

So far, after build the nbm file, we can test our module. First, you should use the netbeans update center ("Tools"->"Update Center"->"Install Manually Downloaded Modules") to install the new module.
After install the module, you could click the "View" menu, we can see a sub menu named "Mp3 renamer", after click it, the Mp3 Renamer panel will popup. So, you can see, the netbeans module development is easy, and with the help of module development enviroment in the future version, the development work will be easier. Here, I cannot give you too much detail information because it will be too long, if you are interested in it, you can send email to me and ask for the demo source file.

Enjoy~

( 2005年03月29日, 06:20:59 下午 GMT+08:00 ) Permalink 评论 [6]
20050328 星期一 2005年03月28日

Netbeans RCP In Action (1)

These days, I have investigated the Netbeans RCP(Rich Client Platform), and developed some module on it. Netbeans is not only the Java IDE, Netbeans.org has provided netbeans platform as an application runtime for build rich desktop application, just like eclipse platform. The "plugin" here is called "Module". Every module is a "nbm" file that could be loaded by their module class loader. The module's information is stored in the manifest file in the Module file.

The netbeans platform has been developed since 1999 when NetBeans 3.0 was rewriten, and the latest version is 4.0. With it, developer could focus on the business logic and NetBeans platform will provide ways to handle module management, UI management, preference management and etc. and it provides rich APIs to help the developer to do customization. see more at http://www.netbeans.org/products/platform.

Like Eclipse, there's also the extension concept in Netbeans Module Runtime, moreover it is based on a J2SE standard for extension registration - META-INF/services. You can checkout the detail information from here. And NetBeans Service registry is also based on J2SE standard extension mechanism (http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html#Service%20Provider).

Netbeans's Module runtime support dynamic module register/unregister/update feature (deploy the module on the fly), which are not supported in Eclipse 2.1(But have already been supported by Eclipse 3.0 using OSGi standard). And Netbeans RCP provide the module update center to help the developer to manage the modules.

After the release of Netbeans 4.0, most of the IDE related things have already been striped out from netbeans platform, and the core size of netbeans platform core has been downsized.

Netbeans has a long history, the story is very interesting, also, there's many applications that already take the advantage of Netbean RCP, you can check out detail information here.

Currently, there's no module development enviroment in netbeans, so the module development work is a little hard, and the beginning learn curve is a little higher. Hope we will get the "MDE"(so called :-)) in the later version. here's the road map of Netbeans.

Then, how to develop a module using netbeans platform? From my experience, it's not so hard. Stay tuned, I will give the demo in the later chapter..

( 2005年03月28日, 11:42:07 下午 GMT+08:00 ) Permalink 评论 [1]
20041219 星期日 2004年12月19日

Netbeans 4.0 announced

Netbeans 4.0 has kicked off. I have already downloaded one to try, sounds good. It makes great improvement than the previous one, and among the features, what attract me most is :
1) Full J2SE 5.0 support;
2) Ant based project;
3) J2ME support - MIDP 2.0 and CLDC 1.1;
How about it? Don't hesitate, just try it. :P ( 2004年12月19日, 03:16:07 下午 GMT+08:00 ) Permalink
20041216 星期四 2004年12月16日

Desktop Search is Booming

AskJeeves announces Desktop Search, I have download one here. Plus MSN Desktop Search, Google Desktop Search, Copernic Desktop Search, and Yahoo's soon coming one, desktop search is booming. ( 2004年12月16日, 11:39:52 上午 GMT+08:00 ) Permalink 评论 [11]
20041214 星期二 2004年12月14日

Using spin lock in your code

Today, my friend ask me to review some code of him, his code will encounter some unexpected error. He's very confused and worried. After digging into the code, I found the problem.
Here's the code slice :
    private boolean done;
    private Message[] messages;
    ... ...
    synchronized(this) {
        if(!done || messages ==null)                                     //    1
           try {
                wait();                                                  //    2 
           } catch (InterruptedException e) {
                e.printStackTrace();
           }
           ...
           dispatchMessage(messages);                                   //    3
           ...
    }
    dispatchMessage(Message[] messages) {
        int length = messages.length;                                   //    4
        ... ...
        messages = null;
    }
When the program run, it will throw NullPointerException sometimes, though very infrequent. And just because of its infrequence, it's hard to debug.
But when go through this code slice, I think Java Expert can learn where's the problem.
Try to imagine such scenario:
1) messages is null
2) Thread 1 check the condition in position 1and waiting  in position 2, and it will release the lock, So other thread can obtain it;
3) Thread 2 check the condition in position 1and waiting  in position 2 too;
4) When we get the message and notify all threads using notifyAll(), both thread 1 and thread 2 will be awaked but only one thread will obtain the lock.
5) Assume thread 1 will get the lock, and it will dispatch the message using dispatchMessage. after dispatching the message, it unreference the messages.
6) When thread 1 finished dispatching the message and release the lock. Thread 2 will obtain the lock, however,  NOW, messages is null, so it will throw NPE.
Then, how to solve the problem? Yeah, it should use spin lock here. So, it will re-check the condition after being awaked and will avoid such problem.
That is, it should be
    while(!done || message ==null)
    ... ...
And this trick is called spin lock(reference1) , you can see detail discussion in this book (practice 54).
BTW: You also can find this trick in "Effective Java", in item 50 - "Never use wait out of loop". And, this two book is really good and worth reading. :-)

Reference:
1) "Pratical Java" - Peter Haggar
2) "Effective Java" - Joshua Bloch
( 2004年12月14日, 09:29:59 下午 GMT+08:00 ) Permalink 评论 [6]