Saturday 11 October 2008

新网站上线 欢迎大家

网站交易中心 在这里你可以购买或者出售你的网站。
网站信息发布中心 在这里有各种交易信息的发布。同时提供
一些软件的免费使用(附有源码)。
网站博客系统 这里你可以注册自己的博客。一个账户无限量博客
联系方式:support@websiteempire.cn
QQ:563828566
MSN:zhuhailin123@hotmail.com

Sunday 28 September 2008

排序算法的实际应用

上次在研究算法的时候详细的介绍了快速排序。
今天有个朋友托我将一些域名排序,按域名长度进行排序。
我看了轨迹至少有300多万行,处理出的结果(txt文件)多大将近100M.
数据量好大啊。
下面是程序清单。核心算法还是复用上次研究过的排序算法。由于数据量巨大,内存会溢出,所以基本解决解决方式是先将文件分段成多个小文件,再分别排序,最后合并到一个文件,删除那些小文件。这对性能造成了影响。所以我直接全部在内存中运算。

五个文件。
Compare.java接口 定义比较排序方式的接口
StringCompare.java Compare的实现类 比如我们这是以域名长度为排序结果
QuickSortVector.java 快速排序算法
GetFile.java 负责文件的输入输出
Main.java主函数入口


——————————————————————————
package sort;

interface Compare {
boolean lessThan(Object sou, Object des);
boolean lessThanOrEqual(Object sou, Object des);
}


——————————————————————
package sort;

public class StringCompare implements Compare
{

public boolean lessThan(Object sou, Object des)
{
return ((String)sou).length()-((String)des).length()<0;
}

public boolean lessThanOrEqual(Object sou, Object des)
{

return((String)sou).length()-((String)des).length()<=0;
}

}
————————————————————————————————
package sort;

import java.util.Vector;

public class QuickSortVector extends Vector{
private Compare compare;
public QuickSortVector(Compare com){
this.compare=com;
}
public void sort(){
quickSort(0,size()-1);
}
public void quickSort(int left,int right){
if(right<=left)
return ;
else{
Object pivot=elementAt(right);
int leftPtr=partition(left,right,pivot);
quickSort(left,leftPtr-1);
quickSort(leftPtr+1,right);
}
}
public int partition(int left,int right,Object pivot){

int leftPtr=left-1;
int rightPtr=right;
while(true){

while(compare.lessThan(elementAt(++leftPtr), pivot)){}
while(rightPtr>0&&compare.lessThan(pivot, elementAt(--rightPtr))){}
if(leftPtr<rightPtr)
swap(leftPtr,rightPtr);
else break;
}
swap(leftPtr,right);
return leftPtr;
}
public void swap(int left,int right)
{
Object temp=elementAt(left);
setElementAt(elementAt(right), left);
setElementAt(temp, right);



}
}
————————————————————————————————————
package sort;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class GetFile
{
private File file;
private File newFile;
private QuickSortVector qsv;
BufferedReader br=null;
BufferedWriter bw=null;
public GetFile(String file,String newFile,QuickSortVector qsv)
{
this.file=new File(file);
this.newFile=new File(newFile);
this.qsv=qsv;

}
public void process(File dir)
{

if (dir.isDirectory())
{
File[] dirs = dir.listFiles();

for (File temp : dirs)
{
if (temp.isDirectory())
{
process(temp);
} else if (temp.isFile())
{
try
{

getQSV(temp);

} catch (IOException e)
{

e.printStackTrace();
}

}
}

} else
{
try
{
getQSV(dir);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
public BufferedReader getReader(File file)
{
BufferedReader br=null;
try
{
br=new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return br;
}
public BufferedWriter getWriter(File file)
{
BufferedWriter bw=null;

try
{
bw=new BufferedWriter(new FileWriter(file));
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

return bw;
}
public QuickSortVector getQSV(File file) throws IOException
{
br=getReader(file);


String temp=null;
while((temp=br.readLine())!=null)
{
qsv.addElement(temp);
}
br.close();
qsv.sort();
bw=getWriter(new File(this.newFile.getPath()+File.separator+file.getName()));

for(Object cc:qsv)
{
try
{
System.out.println((String)cc);
bw.write((String)cc+"\n");
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
bw.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

return qsv;
}

}
————————————————————————————————————————
package sort;

import java.io.File;
import java.io.IOException;

public class Main
{
// private qsv;

public static void main(String[] args)
{
Compare compare=new StringCompare();
QuickSortVector qsv=new QuickSortVector(compare);
GetFile getFile=new GetFile("D:/sort","D:/sort/result",qsv);
getFile.process(new File("D:/sort"));
[code=Java][/code]


}

}

Tuesday 19 August 2008

观察者模式 observer 模拟监听器的实现

学过awt,尤其是swing的同学就知道,swing中observer模式被大量的使用。比如,button.addActionListener(...)后,一旦你点击button后就能触发相应的事件。很多同学一定想知道内部的机制。今天我正好也对这个议题感兴趣,那么我们一起来看一下。
假设我有一台电脑。电脑里面有一个事件,当你按下电源按钮的时候,那么显示器会亮,电源指示灯也会亮。
这是典型的一个类似于GUI中按钮事件模拟。
我们来分析一下需要几个类
电脑肯定是需要的,我们得出Computer类。Computer类内部有一个按电源按钮的动作,我们叫做clickButton.这个事件我们叫做EventPowerOn.于是得出了EventPowerOn类。另外,对比GUI里面的button,他们都会添加监听器,所以应该有个监听器类,我们叫做EventPowerOnListener。好到这里我们基本上找出了几个必须的类Computer,EventPowerOn ,EventPowerOnListener
我们写出他们的框架:
public class Computer implements Runnable{


public void clikButton(){}//该方法如果被调用,那么说明电源按钮被按下

}

public class EventPowerOn {
private Object source;//事件的来源,也就是时间是由哪一个对象激发的
private long time;//这个属性是随意添加的 比如社么时候电源按钮被按下

public EventPowerOn( long time, Object object) {
super();
this.source = object;
this.time = time;

}
public Object getObject() {
return source;
}
public void setObject(Object object) {
this.source = object;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}

}
public interface EventPowerOnListener {
public void performanceToPowerOn(EventPowerOn eventPowerOn);//改方法是电源按钮被
//按后应的响应
}
刚才我们说,电源按钮被按下,那么显示器和电源指示器会变亮。那么显示器和电源指示器应该都另外做一个类
所以有:
public class Screen implements EventPowerOnListener{

public void performanceToPowerOn(EventPowerOn eventPowerOn) {
System.out.println(eventPowerOn.getTime());


System.out.println("Screen is on");

}

}
public class Light implements EventPowerOnListener{
public void performanceToPowerOn(EventPowerOn eventPowerOn) {
System.out.println(eventPowerOn.getTime());


System.out.println("power light is on");

}
}
为什么我们要用他们实现监听器类呢,因为对computer来说,他们都是监听器。一旦电源按钮被按下,显示器和电源指示器就应该要有反应。
那么如何将screen 和light添加进computer 呢。我们做如下的改动
public class Computer {

private List listeners=new ArrayList();

public void addEventPowerOnListener(EventPowerOnListener eventPowerOnListener)
{
listeners.add(eventPowerOnListener);
}
public void clikButton(){
for(EventPowerOnListener temp:listeners)
{
temp.performanceToPowerOn(new EventPowerOn(System.currentTimeMillis(),this) );
}
}

}
好了,一个模拟的例子就完成了。我们来测试一下:
public class testObserver {
public static void main(String[] args){
Computer computer=new Computer();
Screen screen=new Screen();
Light light=new Light();
computer.addEventPowerOnListener(screen);
computer.addEventPowerOnListener(light);
computer.click();



};
}
看戏结果:
1219215665656
Screen is on
1219215665656
power light is on
说明clickButton,那么显示器和电源指示灯都会亮。我们还可以添加另外一些监听器,比如,硬盘会转等。。。只需实现listner接口以及添加到computer的监听列表即可。。。
(最近回过头来看java的一些基础的东西,看swing的时候,突然很想知道observer模式到底是则么实现的,研究了一下,看了一些源码,有了些心得,就顺便写出来)

内嵌接口 内部类 匿名类 内嵌类

内嵌接口与内部类(nesting interface and inner class)
Nesting 接口和内部类 有诸多有趣的特性。尽管我们平时用的不是很多,但在很多时候能够让你的设计更优雅些。
这里我采用了 java思想变成里面的例子,因为该例子简单易懂,毕竟是个牛人写的呵呵(为了演示方便,我修改了一些内容)
下面是一个claass A类
class A
{
interface B
{
void f();
}
public class BImp implements B
{
public void f() {}
}
private class BImp2 implements B
{
public void f() {}
}
public interface C
{
//(7)private interface M{}
void f();
}
class CImp implements C
{
public void f() {}
}
private class CImp2 implements C
{

public void f() {}
}
private interface D
{
//(8)private interface M{}

void f();
}
private class DImp implements D
{
public void f() {}
}
public class DImp2 implements D
{
public void f() {}
}

public D getD()
{
return new DImp2();
}
private D dRef;
public void receiveD(D d)
{
dRef = d;
dRef.f();
}
}

interface E
{
interface G
{
void f();
}
public interface H
{
void f();
}
void g();

}


接着是一个测试类

public class NestingInterfaces {
public class BImp implements A.B {
public void f() {}
}
class CImp implements A.C {
public void f() {}
}
// Cannot implement a private interface except
// within that interface's defining class:
//! class DImp implements A.D {
//! public void f() {}
//! }
class EImp implements E {
public void g() {}
}
class EGImp implements E.G {
public void f() {}
}
class EImp2 implements E {
public void g() {}
class EG implements E.G {
public void f() {}
}
}
public static void main(String[] args) {
A a = new A();
// Can't access A.D:
//(1)A.D ad=a.getD();
//(2) A.DImp2 ad =(A.DImp2) a.getD();
//(3) A.B ab=a.new BImp();
//(4) a.getD().f();
//(5) ((A.Dimp2)a.getD()).f();



// Cannot access a member of the interface:
//! a.getD().f();
// Only another A can do anything with getD():
A a2 = new A();
a2.receiveD(a.getD());
}
} ///:~

在举例之前,我们先看看A类。A类是完全正确的。内嵌类的接口可以有访问修饰符。这和我们平时接触的接口有很大区别,而且修饰符也对其他类的访问有很大的影响。在A内部,大部分访问时不成问题的。但在NestingInterfaces类里面就有许多值得思考的地方了

我们做的主要测试都在第二个类的main 方法里面。我将它们注释掉,并且标上记号,方便讲解。
(1) 会报A.D不可见。原因是D为私有接口。
(2) 这个没有问题。原因在于Dimp2是公有类 如果是Dimp就不行了。另外虽然getD ()方法内部是return new Dimp2();当时返回的仍然是A.D,所以需要类型转换。这个我也没弄明白。
(3) 这句也没问题。
(4) 这个仍然提示A.D不可见。问题同(2)
(5) 这个可以运行
另外需要注意的一个问题是
A类中的(7),(8)都会提示应该声明为public,说明了接口套接口时,内部接口必须为public ,当然你也可以省略修饰词,他会自动为public。


上面的例子是关于内嵌接口的。下面我们再看看内部类有什么特点。
先看第一个演示的类

public class Parcel1 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
// Using inner classes looks just like
// using any other class, within Parcel1:
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tanzania");
}
}
正如注释所说的,使用内部类就如同你使用其他一般的类一样,前提条件是你在外部类中使用他们,这里的外部类是Parcel1.
第二个例子:
public class Parcel2 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Destination to(String s) {
return new Destination(s);
}
public Contents cont() {
return new Contents();
}
public void ship(String dest) {
Contents c = cont();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tanzania");
Parcel2 q = new Parcel2();
// Defining references to inner classes:
Parcel2.Contents c = q.cont();
Parcel2.Destination d = q.to("Borneo");
}
}

现在我们可以看到得出一个结论:
除了在外部类的非静态方法中,如果我们需要实例化某一个内部类,那么实例化的形式是OuterClassName.InnerClassName;
下面仍然是类是于上面的例子,但做了一些变动:

public interface Contents {
int value();
}
public interface Destination {
String readLabel();
}
class Parcel3 {
private class PContents implements Contents {
private int i = 11;
public int value() { return i; }
}
protected class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
public Destination dest(String s) {
return new PDestination(s);
}
public Contents cont() {
return new PContents();
}
}

public class TestParcel {
public static void main(String[] args) {
Parcel3 p = new Parcel3();
Contents c = p.cont();
Destination d = p.dest("Tanzania");
Parcel3.PContents pc = p.new PContents(); //错误,无法实例化
}
}
正如在源代码中最后一句所暗示的,我们可以给内部类添加访问修饰符,我们知道,平常的类我们只能是public 或是包属性。而不能是private或者protected。但是内部类却可以。另外,上面代码和上上面代码还有一个不同点是Content 和Destination 类都实现了各自的接口。从代码封装来看,我们根本无法知道具体的实现类,这也许是内部类另外一个有用只处。

上面的都是一些内部类基础的性质。下面我们谈谈他的高级一点的东西,其中也涉及到了匿名类的一些东西。(PS:有时候我们也别他深究,比如学汉字,只要学会5000个基本的就好了,没必要把康熙字典中的五万个汉字都背下来,所以下面的了解就好)
public class Parcel4 {
public Destination dest(String s) {
class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
return new PDestination(s);
}
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Destination d = p.dest("Tanzania");
//(9)Destination d=p.new Destination(“kitty”);
}
}
这一段代码 不知大家看出和上一段的代码之间的区别没。对,Pdestinatio类被放在外部类的一个方法里面。其实,内部类可以放在外部类的任何一个作用域中。
自然由于有作用域的缘故,那就应该注意他的生命周期。比如(9)中的代码就是错误的,应为编译器根本无法解析Destination.

下面我们再看看匿名类的用法与注意事项:
public class Parcel6 {
public Contents cont() {
return new Contents() {
private int i = 11;
public int value() { return i; }
}; //注意这里有个分号
}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
Contents c = p.cont();
}
}

注意到匿名类的语法:第一 new 后面接的是要实现的接口,当然也可以是一个类。第二,后面接你具体实现Contens接口的代码或者类中需要的方法。第三,匿名类的结尾需要分号标志结束。

下面嗨哟一段代码
public class Parcel8 {
// Argument must be final to use inside
// anonymous inner class:
public Destination dest(final String dest) {
return new Destination() {
private String label = dest;
public String readLabel() { return label; }
};
}
public static void main(String[] args) {
Parcel8 p = new Parcel8();
Destination d = p.dest("Tanzania");
}
}
如果在方法dest中传递的形参如果不是final类的话,编译器就会报错。这也是很重要的一点,往往会被人忽略,不过幸运的是编译器也会提示你,你很快就会纠正过来。不过下面就有一个有趣的是奇怪了,让我们来看看---
abstract class Base {
public Base(int i) {
System.out.println("Base constructor, i = " + i);
}
public abstract void f();
}

public class AnonymousConstructor {
public static Base getBase(int i) {
return new Base(i) {
{
System.out.println("Inside instance initializer");
}
public void f() {
System.out.println("In anonymous f()");
}
};
}
public static void main(String[] args) {
Base base = getBase(47);
base.f();

}
}
你会惊讶的发现,传递给Base的i 竟然不是final的。很郁闷吧,呵呵,其实你加上final也是没有问题的。但是为什么能够传递一个非final的值,原因很简单,编译器规定,如果这个数十给构造函数的话,并且没有在匿名函数起的地方使用,那么可以不是final的。不过我的建议是为了简单起见,我们不妨加上final。
PS:内部类有几个限制:一,内部类不能再嵌套一个内部类,第二,内部类不允许有静态方法与变量

此外,内部类还有很大的好处,他能够无条件的访问外部类的一切,包括私有变量。这在图形设计里面用的很广泛。比如你的一个button按钮需要实现一个监听器用来实现事件处理,那么你需要一个监听器类,如果你把它当成一个通常的类来用的话,那么监听器类如果需要访问被监听类的成员便只能通过构造函数或者传递一个类实例进去,并且要提供相应的访问它私有成员变量的公共方法。而使用内部类就可以简单的解决这一个问题,我们来看一下一个具体的实例:
package com.allwefantasy.java2d;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.*;

public class Button extends JFrame
{
private JButton jbutton;
private Container container;
private JTextArea jtext;
class buttonLisener implements ActionListener
{

public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jbutton)
{
jtext.setText("awesome,get it");
}

}

}
public Button()
{
container=getContentPane();
jbutton=new JButton("kitty");
jtext=new JTextArea();
jbutton.addActionListener(new buttonLisener());
container.add(jbutton,BorderLayout.SOUTH);
container.add(jtext,BorderLayout.NORTH);
}
public static void main(String[] args)
{
Button button=new Button();
button.setBounds(100, 100,200, 300);
button.setVisible(true);
button.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

button.addWindowListener(new WindowAdapter()
{
public void windowClosed(WindowEvent e)
{
System.exit(0);

}
});
}
}
通过观察我们可以发现,在内部类buttonLisener中,我们设置button类的JtextArea的值的时候我们是直接调用jtext.setText("awesome,get it");并没有传递外部类的任何参数进去。倘若我们将内部类作为一个平常的类定义,那就很麻烦了。另外值得一提的是,如果将内部类当作一个一个内部匿名类的话,将可以简化代码。如上上面的代码可以改成如下的:
jbutton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jbutton)
{
jtext.setText("awesome,get it");
}

}
});
同时删除上一个内部类。不过个人不喜欢这样,因为感觉这样的话可读性变差。

写了一个早上了。呵呵本唉想留在后面写的,不过还是一鼓作气的写完比较好。
最好一个议题是:如果我觉得内部类能够访问外部类的一切,这总是让人觉得不爽,那我们怎么办?
给内部类添加一个static 描述符。Thinking in java 的作者将此事的内部类成为nesting class(内嵌类)(PS:不知道这么翻译是否准备去 呵呵)
(PS again 前面我讲的一些限制在内嵌类中并不是限制)

内部类还有很多性质,大家可以多多讨论。对于这篇文章大家如有疑问或者认为哪里有错误可以给我邮件:allwefantasy@gmail.com

Wednesday 13 August 2008

如何制作Java可执行程序以及安装程序

首先我们介绍一下生成 运行Java程序的三种方式-----
Java 生成的jar包执行方式一般有三种:
1直接用系统j2se binnary执行。由于jar包也可以用winrar打开,造成冲突,你可以将文件关联设置一下即可。这样的话jar包和.exe文件并无二致。而且不损失其平台型。
2 编写脚本。在windows下为.bat ,在linux 或者unix下为.sh。其实个人感觉这个更简单。而且很多大程序也是用这种方式运作的。比如tomcat 以及weblogic都是以这种脚本的方式启动。好处是可以设置各种系统环境变量,检测运行的环境,改变启动参数等等。比如在windows下我们只要加一句:start java –jar xxx.jar就可以了。
3 利用各种各种第三方工具将jar包制作成.bin(unix),或者.exe(windows)文件。但这是以失去跨平台特性为条件的。当然好处是带来了更好的用户体验。
第一种只要你安装了j2se就可以
第二种 我们可以举个例子
假设有个allwefantasy.jar的jar包(里面含有manifest文件),于是在相同目录下我建一个allwefantasy.bat(名字可以随意定,如果是在linux下平台就改成sh后缀名)。内容为
start java –jar xxx.jar
。以后双击就可运行。
第三种是我这篇文章的重点。
将 jar包包装成exe可执行文件
其实这种方式在JDK里面就在应用了。不知道你有没有注意到,%JAVA_HOME%\bin里面全是.exe文件,但仔细看看这些文件都只有几个kb而已,这是为什么呢,因为这只是一种wrapper.包装,真正在运行的仍然是jar文件。也可以称作伪exe文件。那么,如何将jar文件制作成可以直接运行的exe文件呢?这里我介绍两款我用过的。NativeJ 以及开源的jsmooth.
我个人比较喜欢用开源的,呵呵那先来介绍一下Jsmooth吧。
图片(2)
使用很简单,在Skeleton选项卡中的第一个下拉框中windowsed wrapper.
图片(4)
接着选择Executable选项卡,第一个空是你要生成的exe文件是叫什么,你自己随意定。第二个空的你想给自己的exe文件弄个什么图标,你可以实现做好一个ico图形文件然后使用。
第三个空就是你jar包所在目录。
图片(6)
在Application选显卡中第一个空粘帖你的 main-class 的全路径。不知道我说清楚了没,也就是你主函数所在目录的包名+主函数名字。比如我要讲的例子中drawsmart.itsv.AppMain。
然后再勾选use an embedded.jar.
最后选择你所需要的jar包就可以了。
最后点击编译按钮就好了。Project –compile—

接着介绍nativeJ,顾名思义,nativej就是本地化java的意思。
这个软件需要购买,不然启动的时候会弹出可恶的框框,跟可恶的是生成的exe。文件在执行的时候还会弹出申明这个程序是由它生成的。。
呵呵 抱怨的话不多讲,做软件的人也不容易。
图片(8)
一开始用的时候也觉得莫名其妙,不得要领,后来琢磨了一下,才闹明白。你事先建立一个目录里面,并且在目录里面建一个空的后缀名为njp文本文件。
然后点击new project wizard,
图片(10)
选择刚才建好的工程文件就可以了。接着就是依次填入一些参数。参数跟Jsmooth差不多,主要有两个,主类的全路径(包名+类名)以及jar包。
最后就能生成我们期待的exe文件了。
图片(12)
这是我生成的文件。
需要注意的是Jsmooth 和nativeJ生成的exe文件还是有所不同的。我不知道设置会不会改变这种不同。
nativeJ中,如上图所示,由于jar并没有将所有的文件都打入包中,比如images.所以生成的exe文件依然是以来jar包以及其他文件的。个人感觉有点像bat文件。
而在jsmooth中,生成了一个exe文件,但是文件却很大,似乎包含了整个jar包以及资源文件,可是却不能单独执行(为什么,我也没弄明白)。
图片(14)
如何为java程序制作安装程序
制作安装程序并不是一项简单的工作。特别对于大型程序来说。你看oracle光安装就的花你半个小时。安装制作程序有很多,大型商业类的有intallAnyWhere 以及installShield .功能超级强大,但毕竟是商业软件,是需要花银子的。此外,因为功能强,学习他的曲线也是比较陡峭的。
这里我还是介绍一个开源的软件。IzPack。你可以到官网去下。
在安装的时候你可以看到他用自己做的安装界面。
图片(16)
安装后必须自己找到他的目录。这里有两点大家可能不习惯,第一,他没有图形界面,第二,他在你给他写好他所需要的install.xml文件时候,是无法运行的。
也许你还不太理解。没关系,我们讲讲他的设计理念。
安装程序无非就几个界面板块,语言选择,如上面的第一副图片,许可申明,如第二副图,安装进程,安装结束界面等。在IzPack中这些叫面板。IzPack就是利用install.xml文件配置这些面板。当然他还有很多内部细节,比如注册表的注册等,当然这是另外一回事了。然后生成一个jar包(又是jar包,为什么不直接生成exe文件呢,呵呵这个我也不知道,你得去问设计的人,呵呵PS:其实还是为了跨平台)。
那么如何写install,xml 文档呢,说明书有一百五十多业,还是自己慢慢看。不过我可以拿一个自己做的范例来看看。
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<installation version="1.0">
//info 主要是一些版本 作者信息

<info>
<appname>我的画画本</appname>
<appversion>1.4 beta </appversion>
<authors>
<author name="GuanSheng" email="wgs@superman.org"/>
<author name="HailLIN" email="zhl@hisdomain.com"/>

</authors>
<url>http://www.superman.net/</url>
</info>

//guiprefs主要设置安装界面的大小,以及是否可以改变尺寸
<guiprefs width="640" height="480" resizable="no"/>

//这里很java里面的国际化很像,我没数过,但IzPack支持很多国家的语言,我这里面选了 英文以及中文。注意,他的语言的缩写和java里面不一致,你要参考文档
<locale>
<langpack iso3="eng"/>
<langpack iso3="chn"/>
</locale>


//资源文件爱你,我这里放了许可申明以及阅readme文件

<resources>
<res id="LicencePanel.licence" src="Licence.txt"/>
<res id="InfoPanel.info" src="Readme.txt"/>
</resources>


//这个就是各个板块了 比如开始,安装,申明板块都在这定义了
<panels>
<panel classname="HelloPanel"/>
<panel classname="InfoPanel"/>
<panel classname="LicencePanel"/>
<panel classname="TargetPanel"/>
<panel classname="PacksPanel"/>
<panel classname="InstallPanel"/>
<panel classname="FinishPanel"/>
</panels>


<packs>
<pack name="Base" required="yes">
<description>The base files</description>
<file src="Readme.txt" targetdir="$INSTALL_PATH"/>
<file src="Licence.txt" targetdir="$INSTALL_PATH"/>
<file src="kitty.exe" targetdir="$INSTALL_PATH"/>
<parsable targetfile="$INSTALL_PATH/kitty.exe"/>
//文件复制到安装文件夹里面就靠这个了
</pack>
<pack name="image" required="yes">
<description>The documentation</description>
<file src="images" targetdir="$INSTALL_PATH"/>

</pack>
<pack name="xmlfile" required="yes">
<description>The sources</description>
<file src="xmlfile" targetdir="$INSTALL_PATH"/>
</pack>
<pack name="temp" required="yes">
<description>The sources</description>
<file src="temp" targetdir="$INSTALL_PATH"/>
</pack>
<pack name="drawflow" required="yes">
<description>The sources</description>
<file src="drawflow3_0.jar" targetdir="$INSTALL_PATH"/>
</pack>

<pack name="service" required="yes">
<description>The sources</description>
<file src="service.ico" targetdir="$INSTALL_PATH"/>
</pack>
<pack name="addon" required="yes">
<description>The sources</description>
<file src="add-on" targetdir="$INSTALL_PATH"/>
</pack>
</packs>

</installation>




写好这个文件后将它放在你要制作成安装文件的主目录下,然后用compile.bat运行它,就能得到一个jar文件(PS:注意,在cmd 中一定要在install所在目录执行install不然会提示找不到各个文件,我就被他卡在这很多时间)
那么生成一个jar文件有什么用呢,呵呵,别急
看最后一步


将jar包的安装程序转换成exe安装程序
实际上到这一步,就是用jsmooth将jar安装程序wrapper成exe.那么最后就大功告成了。
所以用了三个步骤。Jar 程序--jsmooth---exe程序----IzPack---jar安装程序---jsmooth—exe安装程序。
当然如果你想更专业点,可以用installsheild或者intallanywhere。简单说说这两个软件,图形界面,可操作性相当的好。而且对于学习用来说,他不需要注册码。唯一的缺点是,如果你不注册,你制作的安装程序在安装的时候就会弹出该产品未注册的提示框。

我也是在网上看到很多网友问着一方面的问题却往往得不到好的解答。所以在此总结一下。希望和大家多多交流。如果有问题可以联系我:
allwefantasy@gmail.com
(注意:我截的图片一直贴不到博客里面,正在解决中。。。。)


Friday 8 August 2008

(转载)详解Eclipse+MyEclipse完全绿色版制作方法

原文地址:http://www.blogjava.net/bolo/archive/2008/08/07/220696.html
现在在Java开发中,使用的开发工具大部分都是Eclipse,并且和Eclipse关系紧密的要数MyEclipse了,但是MyEclipse是一个EXE可执行程序,对于没有安装Eclipse与MyEclilpse的电脑来说,首先得先解压Eclipse,然后再安装MyEclipse,这不光很麻烦,而且还很费时,对于已经安装好的电脑来说,如果哪天电脑出了问题或是Eclipse崩溃了,导致工具不能用,这时又不得不重新安装时,那可真够郁闷滴~~~,因此,大象本着我为人人,人人为我的奉献精神,在此,将Eclipse+MyEclipse的完全绿色版制作方法写出来,和大家一起分享,让大家都能享受到这种方便。
在这里,大象采用Eclipse3.3.1与MyEclipse_6.0.1GA_E3.3.1_Installer版来举例说明,其它的版本做法与此相同。
第1步:下载Eclipse3.3.1和MyEclipse_6.0.1GA
这里我要提醒大家注意一下:下载Eclipse时不要选择3.2的版本,因为MyEclipse6.0需要3.3版本以上的支持,另外就是下载MyEclipse时不要下完全版,而应该只下插件版,我的这个MyEclipse6.0.1的插件版是176M。

第2步:解压Eclipse3.3.1
将Eclipse3.3.1的压缩包解压到D盘根目录下。


做这个绿色版,把它放在根目录下是因为这样做很方便,在这里,大象以D盘为例,来说明制作方法。
第3步:安装MyEclipse6.0.1GA
双击"MyEclipse_6.0.1GA_E3.3.1_Installer.exe"开始安装MyEclipse,在第3步:"Choose Eclipse Folder"时,注意 "Please Choose Existing Eclipse Installation Folder",点击"Choose...",请选择你解压的Eclipse文件夹,选择好之后如下图:

点击"Next",出现"Where Would You Like to Install MyEclipse 6.0.1?",点击"Choose...",选择上面的eclipse文件夹,这时记得在eclipse后面加一个目录名,否则,MyEclipse的安装文件就会全部放在eclipse的根目录下,这可不是我们希望看到滴,设置好之后如下图:

下面的安装没什么好说的,就是一路Next了。安装结束后,可以在eclipse目录下看到有一个"MyEclipse 6.0.1GA"这个文件夹,进去看看,是不是有两个文件夹,两个文件?

OK,到此MyEclipse插件已经安装完成了,下面来进行我们的绿色插件制作。
第4步:插件制作
在eclipse目录下,新建一个文件夹,命名为"ThirdPlugins"(你要取别的名字也可以,不过一定要和links目录里面的配置文件中的路径一致,后面会有说明),将"MyEclipse 6.0.1GA"这个文件夹复制到"ThirdPlugins"目录下,别用剪切喔,这可是刚才安装MyEclipse的目录,等会还要缷载MyEclipse,如果这个目录没有了,到时缷载不了,出了什么问题可不要怪大象喔!
MyEclipse安装好之后,会在eclipse目录下生成一个links文件夹,里面有一个"com.genuitec.eclipse.MyEclipse.link"文件,我们删除它,另外新建一个"MyEclipse 6.0.1GA.ini"文件,内容为:path=ThirdPlugins/MyEclipse 6.0.1GA
保存完之后,我们的插件制作也结束了,然后就是缷载MyEclipse,千万不要直接把那个文件夹删掉,而应该缷载它。


其实所有的插件都可以按这个方式来做,这样做的好处就是,想用就放进去,不想用就删掉,如果放到eclipse的features和plugins里面,会很不好管理。
第5步:配置参数
虽然插件已经安装好了,但是,此时我们还不能启动它,应该对eclipse的启动参数设置一下,提高它的启动速度和运行时的稳定性。在eclipse.exe上点右键,选择"创建快捷方式",在快捷方式上点右键,选择"属性",在"D:\eclipse\eclipse.exe后面加上空格,将这些参数加在后面:
-vmargs -Xverify:none -XX:+UseParallelGC -XX:PermSize=20M -XX:MaxPermSize=128M -Xms256M -Xmx512M
-Xms256M -Xmx512M:这是堆,根据内存大小来设置,比如大象的内存是1G,我就设成256和512,这样一般都够用了。
当然了,你也可以什么都不设置,不过大象还是建议设置这些参数,可以很大程度上提升eclipse的启动速度。在安装完MyEclipse时,还会生成一个eclipse.ini的备份文件,这个不需要,删掉。我们可以修改下eclipse.ini文件,原始的如下:

-showsplash
com.genuitec.myeclipse.product
--launcher.XXMaxPermSize
256m
-vmargs
-Xms128m
-Xmx512m
-Dosgi.splashLocation=D:\eclipse\MyEclipse 6.0.1GA\eclipse\MyEclipseSplash.bmp
-Duser.language=en
-XX:PermSize=128M
-XX:MaxPermSize=256M 其实这个文件为空都没关系,大象试过,全部删除,没有错误,不过我还是建议大家里面至少保留这些东东
-vmargs
-Xms256m
-Xmx512m 我将128改成了256,如果你想在MyEclipse插件中用"MyEclipse 6.0.1"快捷方式来启动的话,可以写成这样
-vmargs
-Xms256m
-Xmx512m
-Dosgi.splashLocation=D:\Eclipse-3.3.1\ThirdPlugins\MyEclipse 6.0.1GA\eclipse\MyEclipseSplash.bmp
最下面一行是启动时,显示MyEclipse的图片,如果没有这句话运行"MyEclipse 6.0.1"快捷方式,则会显示eclipse的启动画面,其实"MyEclipse 6.0.1"快捷方式还是连接着eclipse.exe这个执行程序,在"MyEclipse 6.0.1"上点右键,选择属性,在目标里就可以看到。
第6步:注册MyEclipse
MyEclipse6.0的注册一定要断开网络,否则肯定不成功!
6.0.1GA注册码
Subscriber: administrator
Subscription Code: nLR7ZL-655342-54657656405281154
这里有一点大象要提醒大家注意,如果你电脑上现在正有使用的MyEclipse,就是说已经注册了,那么在C:\Documents and Settings\"自己的用户名" 目录下,会有一个".myeclipse.properties"文件,这时请先备份此文件,然后删除它,断开网络,再来注册MyEclipse6.0.1,成功后如下:



第7步:打包eclipse
到现在所有的工作都已经完成,启动eclipse的速度快不快?好了,该做最后一步操作了,将"configuration"文件夹下的内容除"config.ini"文件外全部删除,另外再把workspace文件夹删除,大象一般会把workspace放在eclipse根目录下,方法是在第一次启动选择路径时把前面的目录都删除,只保留workspace(前面什么都不要保留)。这样方便管理,你要放在其它的地方随便,这个看各人喜好。做完这两步之后,最好还是在eclipse目录下建一个txt文本文件,把上面的注册码放到里面,另外加上一句话:"注册时一定要断开网络,否则肯定注册不成功!"这样以后用时,可以提醒自己一下。里面有注册码,要用时很方便。
在eclipse文件夹上点右键,选择"添加到eclipse.rar",等到压缩完成,至此,终于大功告成!
大家尽管放心按着我的方法试,大象前前后后做了不下十遍,今天又在公司的电脑上做了一遍,图片都是刚刚截取的,嘿嘿,今天老板不在,大象小小的放松一下,写写博客。有了这个压缩包,以后大家在使用时就会方便很多,特别是保存到移动硬盘里,想在哪用就在哪用。哇哈哈哈哈~~~~~~~~祝大家好运,都成功做出来!
(注: 此帖为菠萝大象原创,而非我写的,由于图片链接很麻烦,所以我没提供图片,大家可以到原博客去看看,也算是度原作者的一个支持。。。。。。)

Friday 1 August 2008

xdoclet 遇到 泛型符号出错

用XDoclet tag 生成 hibernate hbm.xml映射文件时 出错.
Error parsing File G:\workbench\futureCore\src\com\hailin\model\ItemCategory.java:Encountered "<" at line 14, column 14.
[hibernatedoclet] Was expecting one of:
[hibernatedoclet] ...
[hibernatedoclet] "[" ...
[hibernatedoclet] "." ...
[hibernatedoclet] "(" ...
凡是我用了泛型的地方,也就是有 <>的地方都会报错...
在网上查了下,所示xdoclet不支持jdk1.5的annotation,把 xjavadoc1.1.jar换成 xjavadoc.1.5.snapshot.jar 也没有用...
到现在也没有解决问题.
只能不使用泛型,郁闷........
还好我的POJO只有十多个 不然改都要改老半天.........
不知道有谁 解决了这个问题不.......

Wednesday 23 July 2008

排序算法 通用化设计

很多了学了各种排序算法比如 冒泡排序,快速排序,可书本上仅仅是介绍几个数字的排序,那么如何把它应用到真正的工作中呢。这事实上是一个算法的通用性设计问题。如果了解过C++ STL的人就知道这种设计思想与原理。

我们这里主要以快速排序为例子具体说明(因为我个人现在兴趣在java,所以实现都用java实现,有时间的话我会分别用C与C++实现)。

知识准备:java 语言,快速排序的实现思想

开发环境:eclipse, jdk1.6

我们先简单的回顾一下快速排序的思想(事实上这个算法并不好讲解,总之,我尽力,有不明白的可以留言或者发邮件联系我(allwefantasy@gmail.com)):

给定一个数组,int[] array={42,8,63,15,94,23,69,75,3,61,37}

这个数组便是我们需要排序的数组。

首先我们选择其中的一个数字,比方说最右边的,37,我们称之为 枢纽(为什么叫枢纽,因为英文pivot翻译过来的)。然后我们想办法把数组中比37小的放在37的左边,比它大的放在右边(我们先不管如何实现这个放置的算法,待会我们再来讨论&&注意,最后的结果是比三十七小的我们都放 在它的左边,大的都在右边,并且37的左边和右边都是无序的),于是便有这么一个数组:3,8,23,15,37,63,69,75,42,61,94(这个结果是通过一定的算法实现的,我们后面会讲,它符合我们上面的 要求。)好了,到了这一部,我们知道 ,接着我们只要排序枢纽(也就是37)左边的和又变得就可以了,37肯定已经在正确的位置,因此我们不用理会它了(原因是什么呢,用脚趾头想下)。我们用前面相同的方法,对3,8,23,15 进行排序,也就是选择15为枢纽,重复上面的步骤,肯定又能确定一个数字的真确位置,比如15的真确位置应该是3,8,15,23。接着我们再对3,8进行排序(你也许会说,这还要排序吗,一眼就能看出来已经是有序的了,但识别忘了,计算机可使很笨的,它不知道),选择8位枢纽,所以排序结果是3,8 。在对3排序(其实已经到了终止条件了,也就是只剩下一个元素)也就是最终37左边的排序结果出来了 是 3,8,15,23。同理可以推出 右边的。

好了,现在可以讲下如何将枢纽放到正确位置上的算法了

42,8,63,15,94,23,69,75,3,61,37

上面11一个数,我们随机选择一个枢纽,前面我们选择37 主要是为了编程序的方便,不然你也可以用 (int) Math.random()*11来随机选择一个。

第1步:left=0,也就是left指向数组第一个元素,也就是42

同理,right=10,指向37

第2步:left递增,如果遇到比37小的就一直递增。如果遇到比37 大的,比如第一个数字,42,那么此时left=0,停止,执行步骤3

第3步:right-1递减,如果遇到比37大的就一直 递减,如果遇到比37小的,停止,比如这里停止在3,也就是right=8,执行第4步

第4步:交换42和3 。继续执行第1步。

终止条件:如果right-left<0,那么就终止

不知道我这么讲大家时候民白了。也许有人更喜欢通过程序来弄明白算法的思想。

下面给出实现的程序:
public int partition(int left,int right,int pivot){

int leftPtr=left-1;
int rightPtr=right;
while(true){

while(pivot>array[++left]){}
while(rightPtr>0&&pivot<array[--right]){}
if(leftPtr<rightPtr)
swap(leftPtr,rightPtr);
else break;
}
swap(leftPtr,right);
return leftPtr;
}
public void swap(int left,int right)
{
int temp=array[left];
array[left]=array[right];
array[right]=temp;

}
}
好了,上面很好解决了一个枢纽放置的问题。下面该如何实现递归循环,将所有的枢纽都排列好呢

其实根据前面的分析,已经有了清晰的思路。下面我们直接用代码说明;
int size=20;
int[] array=new int[size];
public void quickSort(int left,int right){
if(right<=left)
return ;
else{
int pivot=array[right];
int leftPtr=partition(left,right,pivot);
quickSort(left,leftPtr-1);
quickSort(leftPtr+1,right);
}
}
注意前面partition函数返回的是枢纽的位置,应为枢纽已经排好序,所以不需要再排序,所以在quickSort的递归里面不包含他。
整个程序如下:

public class QuickSort {
int size=20;
int[] array=new int[size];
public void quickSort(int left,int right){
if(right<=left)
return ;
else{
int pivot=array[right];
int leftPtr=partition(left,right,pivot);
quickSort(left,leftPtr-1);
quickSort(leftPtr+1,right);
}
}
public int partition(int left,int right,int pivot){

int leftPtr=left-1;
int rightPtr=right;
while(true){

while(pivot>array[++left]){}
while(--right>0&&pivot<array[--right]){}
if(leftPtr<=rightPtr)
swap(leftPtr,rightPtr);
else break;
}
swap(leftPtr,right);
return leftPtr;
}
public void swap(int left,int right)
{
int temp=array[left];
array[left]=array[right];
array[right]=temp;

}
}

既然快速怕需算法我们回顾完了,那么我们学了这个该怎么用呢,比如 我进行排序的不一定是数字啊,可能是字母阿。而且,这些要被排序的不一定在数组里面阿,可能是在vector,Hashtable里面阿,更进步,可能是从数据库里面取出的不确定类型的数据进行排序,如前所述,这涉及到了算法的通用性设计。
我们来分析一下,我们无法通用快速排序算法是因为比较的数据类型不同,但是排序的算法的思想。
编写通用的排序代码时,面临的一个问题是必须根据对象的实际类型来执行比较运算,从而实现正确的排序,而解决方法是“将发生变化的东西同保持不变的东西分隔开”。在这里,保持不变的代码是通用的排序算法,而每次使用时都要变化的是对象的实际比较方法。
我们先来实现一个比较的接口(面向接口编程是被JAVA语言所提倡的,spring便是这种行为的有力证实着)。
interface Compare {
boolean lessThan(Object sou, Object des);
boolean lessThanOrEqual(Object sou, Object des);
}
这是一个比较类。
下面是我改写了前面的快速排序的类;
package com.hailin.www;

import java.util.Vector;

public class QuickSortVector extends Vector{
private Compare compare;
public QuickSortVector(Compare com){
this.compare=com;
}
public void sort(){
quickSort(0,size()-1);
}
public void quickSort(int left,int right){
if(right<=left)
return ;
else{
Object pivot=elementAt(right);
int leftPtr=partition(left,right,pivot);
quickSort(left,leftPtr-1);
quickSort(leftPtr+1,right);
}
}
public int partition(int left,int right,Object pivot){

int leftPtr=left-1;
int rightPtr=right;
while(true){

while(compare.lessThan(elementAt(++leftPtr), pivot)){}
while(rightPtr>0&&compare.lessThan(pivot, elementAt(--rightPtr))){}
if(leftPtr<rightPtr)
swap(leftPtr,rightPtr);
else break;
}
swap(leftPtr,right);
return leftPtr;
}
public void swap(int left,int right)
{
Object temp=elementAt(left);
setElementAt(elementAt(right), left);
setElementAt(temp, right);



}
}

事实上只要把原来int型的改称Object根类就行了。另外,虽然数组的效率比较高,但是不灵活 ,受长度限制,提供的方法少,所以这里我们继承了Vector类。所以里面的size(),elementAt(),setElementAt()方法都是从父类继承过来的。
现在我们可以清楚地看到,假设我们要比较的字符窜,我们只要实现字符窜类的Compare接口 就可以了。
下面我们来实现CompareString类。
public class CompareString implements Compare {

@Override
public boolean lessThan(Object sou, Object des) {
return ((String)sou).toLowerCase().compareTo(((String)des).toLowerCase())<0;

}

@Override
public boolean lessThanOrEqual(Object sou, Object des) {
return ((String)sou).toLowerCase().compareTo(((String)des).toLowerCase())<=0;
}

}
这里大家注意下compareTo()方法,比较此对象与指定对象的顺序,它返回的是一个整数。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。所以我们必须判断然后返回布尔值。
下面我们给出测试程序:
import java.util.Enumeration;

public class TTest {


public static void main(String[] args) {
QuickSortVector qsv= new QuickSortVector(new CompareString());
qsv.addElement("a");
qsv.addElement("M");
qsv.addElement("b");
qsv.addElement("K");
qsv.addElement("z");
qsv.addElement("y");
qsv.sort();
Enumeration e = qsv.elements();
while(e.hasMoreElements())
System.out.println(e.nextElement());




}
}
程序结果:
a
b
K
M
y
z
在写这个程序的时候自己也犯了个小错误,用单步调试 调试了半天才闹出来希望大家能够注意以下:
if(leftPtr
从上面的程序可以看出,如果要比较其他类型的对象,你只要实现相应的Compare类就可以。
这里需要注意的一点。在测试的时候 我们还有一句 qsv.sort().其实我们可以在quickSortVector类中改写elments()方法,这样封装性更好一些。同时我们可以覆盖更多的原有的父类的方法,使之更适合我们的需要。
今天就先写到这里...希望能和大家多多交流。

Sunday 20 July 2008

RSerPoolji简介与安装配置

这几天专门研究下thomas的可信赖服务器池(RSerPool).
RSserPool核心概念: 三个实体元素: Registrar: poolElement: poolUser:
两个专有协议: ENRP(Endpoint HaNdlespace Redundancy Protocol) ASAP (Aggregate Server Access Protocol)
以及一个基础协议: sctp :
下面我们来分别理解下每一个元素于协议的作用于处于什么样的位置 为了方便理解,我们直接举个具体的例子。假设这里我们正在用浏览器上网,那么我们需要连接到服务器上去。 在假设google正在使用我们的RSerPool技术。于是我们敲入www.google.com 于是我们便连接到了google的服务器。但事实上google绝对不仅仅一台服务器,而是很多台。那么假设有一个容器需要协调这么多的服务器工作,我们便有了服务器池的概念(正确,但其范围及概念更加广泛),这有点类似于连接池的概念。那么其中的每一台服务器,我们就叫他poolElement. 想推这些池元素而言,我们这些访问服务的计算机就是poolUser,即池用户。对于服务器池而言,他们需要一个协调维护者,比如存储poolElement每一个的名字或者ID ,如果哪一个当机了,又维护者决定哪一个顶上,所有便有了Registrar的概念。那么我们会想,registrar 是如何和服务器池中的poolElement通信的呢。对需要一个协议,也就是ASAP,聚合服务器访问协议(姑且这么翻译)(注:周老师的译稿我在网上始终打不开,不知什么缘故,原因是我国禁止封锁了这个网站)。一般服务器都需要冗余,Registrars 也不例理外,所以他们之间也需要协调,有协调就有通信,有通信就有协议,于是ENRP 便产生了,也即(端点处理域冗余协议。(是这样的) 我们再看看官方的解释:



The figure above shows the building blocks of the RSerPool architecture, which has been defined by the IETF RSerPool WG in [draft-ietf-rserpool-arch]. In the terminology of RSerPool a server is denoted as a Pool Element (PE). In its Pool, it is identified by its Pool Element Identifier (PE ID), a 32-bit number. The PE ID is randomly chosen upon a PE's registration to its pool. The set of all pools is denoted as the Handlespace. In older literature, it may be denoted as Namespace. This denomination has been dropped in order to avoid confusion with the Domain Name System (DNS). Each pool in a handlespace is identified by a unique Pool Handle (PH), which is represented by an arbitrary byte vector. Usually, this is an ASCII oder Unicode name of the pool, e.g. "DownloadPool" or "WebServerPool".
上面的示意图展示了RSserPool体系的结构的各个模块图。在RSerPool技术中,一个服务器都被名名为一个池元素。在其池中,每个服务器(或池元素)被32比特的PE ID 所唯一标识。PEID 由PE在相相应池注册的过程中随基产生。一系列池构成一个处理域(Handlespace).以前是叫做名字空间,但为了避免于域名系统(DNS)中的概念想混淆改为处理域。在处理域中,每一个池都由一个唯一的由任意字节向量构成的池处理(PoolHandle(PH))所标志。通常情况下,池处理是某个池ASCII的UNICODE名字。比如“下载池”或者"web服务器池“。
Each handlespace has a certain scope (e.g. an organization or company), denoted as Operation Scope. It is an explicit non-goal of RSerPool to manage the global Internet's pools within a single handlespace. Due to the limitation of operation scopes, it is possible to keep the handlespace "flat". That is, PHs do not have any hierarchy in contrast to the Domain Name System with its top-level and sub-domains. This constraint results in a significant simplification of the handlespace management.
每一个处理域都有一个确定的范围(域)(比如一个组织或者一家公司),并且被赋予一个操作域,显然在一个单一的处理域中管理全球因特网池并不是RSerPool的目标。由于控制域的限制,我们很可能去使控制域“平坦”的而非具有层次。也就是说,和域名系统相比,PHs并没有层次结构,比如顶层域含有子域。RSerPool的这种限制简化了处理域的管理。
Within an operation scope, the handlespace is managed by redundant Registrars. In literature, this component is also denoted as ENRP Server or Name Server. Since "registrar" is the most expressive term, this denotation is used in the whole document. PRs have to be redundant in order to avoid a PR to become a single point of failure (SPoF). Each PR of an operation scope is identified by its Registrar ID (PR ID), which is a 32-bit random number. It is not necessary to ensure uniqueness of PR IDs. A PR contains a complete copy of the operation scope's handlespace. PRs of an operation scope synchronize their view of the handlespace using the Endpoint HaNdlespace Redundancy Protocol (ENRP) defined in [draft-ietf-rserpool-enrp,draft-ietf-rserpool-common-param]. Older versions of this protocol use the term Endpoint Namespace Redundancy Protocol; this naming has been replaced to avoid confusion with DNS, but the abbreviation has been kept. Due to handlespace synchronization by ENRP, PRs of an operation scope are functionally equal. That is, if any of the PRs fails, each other PR is able to seamlessly replace it.
在一个操作域中,每个处理域由相应的冗余的Registrars所管理。从含义来看,这个组件也可以被称作ENRP 服务器或者名字服务器。但既然“registrar”是最能表达相应意思的一个词汇,我们在整个文档中都将使用这个词汇。PRs 为了防止出现单点失效(single point failure)必须具有冗余。操作域中的每一个PR都由一个32比特的随机数所标志,我们称作Registrar ID(PR ID).并不需要确保PR IDs的唯一性。一个 PR包含了操作域中处理域的完全拷贝。在操作域中的每个PR都同步处理域的内容通过 Endpoint HaNdlespace Redundancy Protocol(ENRP,端点处理域冗余协议)。旧版协议中使用Endpoint Namespace Redundancy Protocol,这个名字被现在的名字替换,依然是由于避免为了和DNS 想混淆,但它的缩写形式仍然是相同的。由处理域通过ENRP进行同步,一个操作域中的PRs 是功能等同的。。。也就是说PRs中的任何一个PR失效,都可由另一个PR 所代替。
Using the Aggregate Server Access Protocol (ASAP), defined in [draft-ietf-rserpool-asap,draft-ietf-rserpool-common-param] a PE can add itself to a pool or remove it from by requesting a registration or deregistration from an arbitrary PR of the operation scope. In case of successful registration, the PR chosen for registration becomes the PE's Home-PR (PR-H). A PR-H not only informs the other PRs of the operation scope about the registration or deregistration of its PEs, it also monitors the availability of its PEs by ASAP Keep-Alive messages. A keep-alive message by a PR-H has to be acknowledged by the PE within a certain time interval. If the PE fails to answer within a certain timeout, it is assumed to be dead and immediately removed from the handlespace. Furthermore, a PE is expected to re-register regularly. At a re-registration, it is also possible for the PE to change its list of transport addresses or its policy information (to be explained later).
一个PE 可以通过向相应操作于域中的任意PR 请求注册或者注销而将他自己加入或者移出服务器池,这是通过ASAP协议完成的。一旦成功注册,该台PR 就成为相应PE的 Home-PR(PR-H)(有点凹口,也就是说,PE a 向PR b 注册,那么注册成功后b 就称作a的PR-H)。一个 PR-H不仅通知其他的PRs某个PE 的注册与注销,同时也通过ASAP Keep-Alive信息来监视PE的有效性。一个Keep-Alive 信息周期性的被PR-H 发送给PE。如果PE在规定的时限内为能够回答,该PE就被PR-H认为失效,并被移出服务器池。进一步的,一个PE 也被要求周期性的从新注册。在从新注册中,PE 就有可能改变传输地址列表以及策略信息守(这将在稍后解释)。
To use the service of a pool, a client - called Pool User (PU) in RSerPool terminology - first has to request the resolution of the pool's PH to a list of PE identities at an arbitrary PR of the operation scope. This selection procedure is denoted as Handle Resolution. For the case that the requested pool is existing, the PR will select a list of PE identities according to the pool's Pool Member Selection Policy, also simply denoted as Pool Policy.
为了使用池服务,客户,也就是Pool User(PU),首先必须请求操作域中的任意一个PR对池的PH(PH也就是前面提到的pool的ID)解析并得到PE ID列表(个人认为的过程:首先PU 给任意某个PR 发送一个PH,也就是Pool 的ID,然乎由PR 进行解析,判断这个相应的池是否存在,如果存在,这根据池成员选这策略得到一张列表返还)。这个过程被称作解析处理(Handle Resolution).在池可用的情况下,PR 会根据池的池成员选择策略(简称池策略)选择一个PE ID 的列表。
Possible pool policies are e.g. a random selection (Random) or the least-loaded PE (Least Used). While in the first case it is not necessary to have any selection information (PEs are selected randomly), it is required to maintain up-to-date load information in the second case of selecting the least-loaded PE. Using an appropriate selection policy, it is e.g. possible to equally distribute the request load onto the pool's PEs.
可能的池策略是随机选择或者选择最少被加载的PE(即最少被使用原则)。第一种情况不需要任何额外的选择信息。第二种情况需要维持一个最新的加载信息。一个合适的策略是经可能的是负荷均匀的落在由每台服务器(PE)上。
After reception of a list of PE identities from a PR, a PU will write the PE information into its local cache. This cache is denoted as PU-side Cache. Out of its cache, the PU will select exactly one PE - again using the pool's selection policy - and establish a connection to it using the application's protocol, e.g. HTTP over SCTP or TCP in case of a web server. Using this connection, the service provided by the server is used. For the case that the establishment of the connection fails or the connection is aborted during service usage, a new PE can be selected by repeating the described selection procedure. If the information in the PU-side cache is not outdated, a PE identity may be directly selected from cache, skipping the effort of asking a PR for handle resolution. After re-establishing a connection with a new PE, the state of the application session has to be re-instantiated on the new PE. The procedure necessary for session resumption is denoted as Failover Procedure and is of course application-specific. For an FTP download for example, the failover procedure could mean to tell the new FTP server the file name and the last received data position. By that, the FTP server will be able to resume the download session. Since the failover procedure is highly application-dependent, it is not part of RSerPool itself, though RSerPool provides far reaching support for the implementation of arbitrary failover schemes by its Session Layer mechanisms.
在接受到PR 返回的PE ID列表后,PU会将其缓存在本地的缓存中,该缓存称为PU-side Cache.一旦缓存溢出,PU江湖再次通过池选择策略选择一个PE并且通过应用层协议建立连接,比如(应用层协议)建立在sctp 或者TCP之上的HTTP(该协议可用于web服务)。建立好连接后,那么服务器的服务将可以使用。假设建立连接失败或者在服务正在使用的时候连接被中断,那么一个新的PE将会被选择。如果PU 端的缓存信息没有过期,PE 将被直接从缓存中选取而无须重复解析过程。在与新的PE重建连接后,应用层信息也将在新的PE中重初始化。重建会话的过程被乘坐Failover过程。以FTP下载为例子,整个failover过程意味着告诉信的FTP服务器文件名字以及被传递接受数据的位置(类似于断点续传中端点的概念)。通过上面的步骤,新的FTP服务器就可以恢复下载的会话。由于failover的是高度程序独立的,应此他的实现并不是RSerPool的一个部分,尽管RSerPool在会话层提供了了任意failover模式。
To make it possible for RSerPool components to configure automatically, PRs can announce themselves via UDP over IP multicast. These announces can be received by PEs, PUs and other PRs, allowing them to learn the list of PRs currently available in the operation scope. The advantage of using IP multicast instead of broadcast is that this mechanism will also work over routers (e.g. LANs connected via a VPN) and the announces will - for the case of e.g. a switched Ethernet - only be heard and processed by stations actually interested in this information. For the case that IP multicast is not available, it is of course possible to statically configure PR addresses.
为使RSerPollP组件配置自动化,PRs通过基于IP多播UDP互相传递信息(通知)的。这些通知将被PE或者其他的PRs接受。这可以让其他的PE活PRs学习到d当前操作域中可用PRs的列表。使用IP多播而非广播主要是因为该机制可以工作在路由器上,比如基于虚拟专用网(VPN)连接的局域网(LANs)以及通知将只会被那些对这些信息感兴趣的站点解听到(比如在交换以太网中)。如果IP 多播不被支持的华,当然也可以静态配置如有地址。
下面是安装过程,这整个安装过程并不想象的那么简单。我花了三天多时间才基本装好,还有一些问题依然没有解决。
1,首先是系统要求。我装的是Ubuntu 8.04 -hardy Heron-released in April 2008,是桌面版本的。桌面用的是GNOME.KDE应该没问题。
2 ,软件要求,必须要有GCC 编译器。这个系统默认就会装,但是装的并不全,最好是通过下面两条命令。
sudo apt-get install gcc --build-essensial
sudo apt-get install g++
3 源码 glib, sctplib ,socketapi ,rsplib 准备(这是按照Thomas 安装说明中所要求的,但有问题,至少我装了两次系统都没有解决)
4 安装 glib
sudo ./configure
sudo make
sudo make install
安装没问题。但是当你安装sctplib 时候就有问题了。在检查依赖性时候会出现两种情况:
第一种,提示没哟找到glib,
第二种,提示有某一低版本却找到一高版本。
解决办法有:(最好的)直接安装GTK开发包
输入如下命令:
sudo apt-get install libgtk2.0-common libgtk2.0-dev
这样让人心烦的glib 问题就全被系统自己解决了。
第二中方法是主要是从问题的原因入手,之所以安装好glib 之后找不到glib 是应为glib 被方在了/usr/local/lib目录下,系统是默认不找这个目录的
,我们必须把他发在/usr/lib目录。(在你看些这个目录你就知道,大部分程序包都是放在/usr/lib目录下的,/usr/local/lib却是空空如也)
所以,你必须将执行这些命令
sudo ./configure --prifix=/usr
sudo make
sudo make install
第三种方案是将
/usr/local/lib 目录添加到/etc/ld.so.conf中去。
事实上我个人觉得应该作两个工作,把第一第三种方法都做一下,应为下面装的一些包也是要放在/usr/local/lib目录下的。
5 安装sctplib
这个没有什么问题。敲那三个命令就可以了。
6安装socketapi
thomas网站上提供的包似乎有问题,因为在make的时候会提示构造函数的什么问题。因此我在linuxQuestion上问了下,可爱的knudfl(http://www.linuxquestions.org/questions/linux-software-2/socketapi-compile-problems-654728/#post3211135 )提供了一个最新的下载地址:http://ppa.launchpad.net/dreibh/ubuntu/pool/main/s/socketapi/。
我编译通过没有问题。
6 安装rsplib
安装最新版本的rsplib 会提示socketapi 版本过低,但我查阅了一下,感觉前面的那个socketapi已经是最高的了,所以我换了个rsplib2.2.0版本后就能顺利依赖性检查
基本没有什么其他问题只是在使用./configure时,使用下面的命令代替
./configure --disale-kernel-sctp
否则提示你的内核没有sctp,你必须手工将sctp继承进内核,很难。应此你可以使用嗯上面我们安装的sctp.
7 单机环境测试
因为至少要三台到四太机器,所以虚拟机是不错的选择。我的博客有具体的虚拟机配置教程,其中包括安装遇到的bug修改问题。 http://coolcat-allwefantasy.blogspot.com/

(感谢周老师的批注与修改)

Wednesday 16 July 2008

(quote)some problems in java development java开发的常见问题(转载)

问题一:做数据库缓存时遇到的问题。HashMap在并发遍历时会报ConcurrentModificationException,即使使用Collections.synchronizedList把Map包起来还是会报这个异常,这个问题很简单,解决办法也简单。第一种解决办法是不要用Map的iterator来遍历,而是用Set(Map.keySet方法)的toArray方法来遍历,这种办法虽然会损耗一定的性能和内存,但比在方法前加synchronized好得多;第二种解决办法用jdk5.0以后的ConcurrentHashMap来实现。【修正:经过测试和验证,第一种方法不行,也就是并发操作MAP而且要求遍历的时候只能用ConcruuentHashMap,在此要感谢写ConcurrentHashMap的专家们。】

问题二:jfreecharts在Linux上不能显示中文,这个问题没有费多长时间就解决了,上网一搜就搞定,解决方法如下: 到网上下载一个linux下的ttf字体,本例用的是zysong.ttf 1.确认%JavaHome%/jre/lib/fonts目录下存在zysong.ttf 2.在%JavaHome%/jre/lib/fonts目录下执行"ttmkfdir -o fonts.dir"命令,重新生成fonts.dir文件 3.确认/usr/share/fonts/zh_CN/TrueType目录存在,如果不存在则mkdir创建 4.确认/usr/share/fonts/zh_CN/TrueType目录下存在zysong.ttf 5.在%JavaHome%/jre/lib目录下,执行 cp fontconfig.RedHat.3.properties.src fontconfig.properties 6.重起resin,OK。
问题三:linux下的too many open files错误,这个问题比较严重,AS4默认打开文件数是1024,如果超过这个数,resin就自动down掉了,非常恶心。解决办法如下: echo 65536 > /proc/sys/fs/file-max 编辑/etc/sysctl.conf 文件,编辑行 fs.file-max = 65536 编辑文件/etc/security/limits.conf,增加行 * - nofile 65536 用ulimit -a 查看,如果看到行open files (-n) 65536就说明对了

问题四:内存泄露,表现出来的特征是CPU占到99.9%,内存由10%左右经过几个小时后慢慢涨到50%,最后死掉。做java的人知道,这个问题非常痛苦,而且没有很好的解决办法,因为直接看代码很难看出来。我原来一直以为问题会出现在缓存上,但仔细想想apache的LRUMap不至于产生内存泄露,尤其我设置了LRUMap最大长度只有10000,10000个内存对象能有多大,后来发现是SmartUpload的问题,改成apache的FileUpload子项目就可以了。另外,我在设置jvm参数时增加了-Xmx2048m -Xms2048m -Xmn768m -Xss512k -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy这些参数,可以回收年老区的内存,现在比较稳定,一般内存占到27%左右就不会再涨了,可能这些参数还不是最优的,有待探索。另外查找内存泄露的软件JProbe我也玩了玩,的确看出其他代码没有明显内存泄露。【修正:上面的参数配置狗P用都没有,内存总是一直在涨。我还尝试了用其他不同方法去回收内存,结果都不太好使,直接用jvm默认的回收方式是最好的,也就是只配置两个参数-Xmx768M -Xms768M效果最好,这样java才真的可以一次性回收几百兆的内存。】

题九:hiberate配置文件的问题,配置不好的话总是会报NESTED Exception,或者多用户并发的时候报错。我想一般人都遇到过了,增加一个c3p0的配置段,尤其注意max_statements设置稍微大一点,原来我设置为100的时候10个用户同时创建记录就会出错。 org.hibernate.connection.C3P0ConnectionProvider 200 20 3600 1000 300 5 false

Sunday 13 July 2008

vmware station 6.0 在ubuntu 中 vmmon 模块编译不成功的解决办法

* unpack VMware-workstation-6.0.3
* go to vmware-distrib/lib/modules/source
* untar the file vmmon.tar (tar xvf vmmon.tar)
* cd vmmon-only/include
* edit the file vcpuset.h
* go to line 74
* change #include “asm/bitops.h” to #include “linux/bitops.h” (Because there are some changes made to the 2.6.24 kernel, it’s not possible to include bitops.h from asm and you will have to include it from the linux directory)
* go back to vmware-distrib/lib/modules/source
* remove the old vmmon.tar file (rm vmmon.tar)
* repack the new vmmon.tar file (tar cvf vmmon.tar vmmon-only)
* remove vmmon-only directory (rm -rf vmmon-only)

Now go to vmware-distrib directory and install vmware as you usualy do. It should work without a glitch.

j3d ubuntu java3d linux解决方法

if you wanna run a application based on java3d ,you should configure the environment .the first step ,download java3d from sun' website.if it a bin file,
do like this:
sudo chmod +x *.bin
sudo ./*.bin
and then bin file will be extracted in the present directory.and in the i386 dir,you will find two so files,put them in the path like:/usr/lib/jvm/jre/i386/
in the ext dir ,there would be three jar files. put them in /usr/lib/jvm/jre/ext path.
and now you can run whatever you like.
PS :
if u use eclipse to develop 3d application based on java ,and some problems occurs ,u can right click the project and choose build path item,and and external jars ,and then choose the three jar files.

something about scim 关于scim中文输入法问题

when you install ubuntu,scim have be installed .you can type :
scim -d
to start it .
if you really be pissed off by typing the command every time .you can follow these steps:
1 export XMODIFIERS="@im=SCIM
2
System--preferences--session .click on add button,type a name and then in the command field type:
scim -d
save it and close.

PS:
sometimes u will find that though you are running scim,but you cannot write with it .maybe you can try this way to fix it:
sudo synaptic
and search scim ,and remove it completely.then run the terminal,type:
sudo apt-get install scim-pinyin
and the softmanager will do the rest.but if the problem still troubles you ,maybe you can restart your computer.
当你安装完ubuntu的时候,scim已经被安装了。你可以启动它利用下面的命令:
scim -d
如果你无法容忍每次启动的时候都要敲一遍命令的话。试着作下面事情。
1 export XMODIFIERS="@im=SCIM
2
系统--首选项--会话 。单击 添加 输入名字并在命令域下输入:
scim -d
保存关闭即可
注:
有时即使启动了scim 在网页上活其他编辑文字软件中也无法使用。这个时候你可以卸载scim并且重装。方法如下:
sudo synaptic
在 synaptic 中搜索 scim ,并单击右键选择全部卸载。
接着在命令行中执行下面的命令
sudo apt-get install scim-pinyin
既可

Wednesday 9 July 2008

socketapi compile problems

socketapi compile problems

when i install socketapi-2.1.0 ,i can pass the ./configure,but when i run the make command,the following message are show:
make all-recursive
make[1]: Entering directory `/home/william/Desktop/RSerPool/socketapi-2.1.0'
Making all in socketapi
make[2]: Entering directory `/home/william/Desktop/RSerPool/socketapi-2.1.0/socketapi'
source='thread.cc' object='thread.lo' libtool=yes \
depfile='.deps/thread.Plo' tmpdepfile='.deps/thread.TPlo' \
depmode=gcc3 /bin/bash ../admin/depcomp \
/bin/bash ../libtool --mode=compile g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c -o thread.lo `test -f 'thread.cc' || echo './'`thread.cc
mkdir .libs
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c thread.cc -MT thread.lo -MD -MP -MF .deps/thread.TPlo -fPIC -DPIC -o .libs/thread.o
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c thread.cc -MT thread.lo -MD -MP -MF .deps/thread.TPlo -o thread.o >/dev/null 2>&1
source='tdstrings.cc' object='tdstrings.lo' libtool=yes \
depfile='.deps/tdstrings.Plo' tmpdepfile='.deps/tdstrings.TPlo' \
depmode=gcc3 /bin/bash ../admin/depcomp \
/bin/bash ../libtool --mode=compile g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c -o tdstrings.lo `test -f 'tdstrings.cc' || echo './'`tdstrings.cc
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c tdstrings.cc -MT tdstrings.lo -MD -MP -MF .deps/tdstrings.TPlo -fPIC -DPIC -o .libs/tdstrings.o
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c tdstrings.cc -MT tdstrings.lo -MD -MP -MF .deps/tdstrings.TPlo -o tdstrings.o >/dev/null 2>&1
source='synchronizable.cc' object='synchronizable.lo' libtool=yes \
depfile='.deps/synchronizable.Plo' tmpdepfile='.deps/synchronizable.TPlo' \
depmode=gcc3 /bin/bash ../admin/depcomp \
/bin/bash ../libtool --mode=compile g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c -o synchronizable.lo `test -f 'synchronizable.cc' || echo './'`synchronizable.cc
g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include -c synchronizable.cc -MT synchronizable.lo -MD -MP -MF .deps/synchronizable.TPlo -fPIC -DPIC -o .libs/synchronizable.o
In file included from /usr/include/signal.h:33,
from synchronizable.cc:44:
/usr/include/bits/sigset.h:118: error: expected constructor, destructor, or type conversion before 'int'
/usr/include/bits/sigset.h:119: error: expected constructor, destructor, or type conversion before 'int'
/usr/include/bits/sigset.h:120: error: expected constructor, destructor, or type conversion before 'int'
make[2]: *** [synchronizable.lo] Error 1
make[2]: Leaving directory `/home/william/Desktop/RSerPool/socketapi-2.1.0/socketapi'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/william/Desktop/RSerPool/socketapi-2.1.0'
make: *** [all] Error 2


and this is the ./configure output:
checking for pkg-config... /usr/bin/pkg-config
checking for GLIB - version >= 2.0.0...
*** 'pkg-config --modversion glib-2.0' returned 2.16.0, but GLIB (2.16.3)
*** was found! If pkg-config was correct, then it is best
*** to remove the old version of GLib. You may also be able to fix the error
*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing
*** /etc/ld.so.conf. Make sure you have run ldconfig if that is
*** required on your system.
*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH
*** to point to the correct configuration files
no
checking for glib-config... /usr/bin/glib-config
checking for GLIB - version >= 1.2.0... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating socketapi/Makefile
config.status: creating cppsocketapi/Makefile
config.status: creating socket_programs/Makefile
config.status: creating cppsocket_programs/Makefile
config.status: creating scripts/Makefile
config.status: creating config.h
config.status: executing depfiles commands

The socketapi package has been configured with the following options:

Build with Maintainer Mode : yes
Build with SCTP over UDP :

sctplib libraries : /usr/local/lib/libsctplib.a
glib_LIBS : -L/usr/lib -lglib
Thread Libraries : -lpthread

CFLAGS : -g -O2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include
CXXFLAGS : -g -O2 -DLINUX -Wall -g3 -O0 -D_REENTRANT -D_THREAD_SAFE -DSCTP_SOCKET_API -I/usr/local/include
LDFLAGS

actually,when i install sctp,there seems to be no glib,so i install glib-2.16.0.But the config setup say glib-2,16,3 was found.notice that the program will find the glib-config ,so i installed the glib-dev ,and solve that problem,but still will show the warning.and the make goes wrong. i also download the socketapi.deb package,but it says glib cannot been found and sometimes say sctp are not found ,but i had installed sctp!damn
plz,someone can fix this problem or who have installed socketapi
successfully show me steps or communicate with me.
my e-mail:allwefantasy@gmail.com
thanks.

Thursday 3 July 2008

how to set default jre

sudo update-alternatives --config java


one sentence work out . Awesome!

i love ubuntu!
there are some commands show information about jre ,jdk.


sudo update-java-alternatives
and you can add some param to show .
for example:

william@william-superstar:/VirtualWorld/eclipse$ sudo update-java-alternatives -l
[sudo] password for william:
java-6-sun 63 /usr/lib/jvm/java-6-sun

Tuesday 1 July 2008

how to uninstall eclipse java compiler

sudo apt-get remove --purge java-gcj-compat

if you wanna intall sun jdk so type this command
sudo apt-get install sun-java6-jdk

ubuntu install realplayer

.rpm and .bin are supported in official website http://www.real.com/linux.
i use alien install realplayer.rpm ,it seems to should to config script ,and when installed ,it donnot work.
so .bin is success .
sudo chmod +x Realplayer11GOLD.bin
./bin Realplayer11GOLD.bin

then like this:
william@william-superstar:~/Desktop$ ./../RealPlayer/RealPlayer11GOLD.bin
Extracting files for Helix installation........................

Welcome to the RealPlayer (11.0.0.4028) Setup for UNIX
Setup will help you get RealPlayer running on your computer.
Press [Enter] to continue...


Enter the complete path to the directory where you want
RealPlayer to be installed. You must specify the full
pathname of the directory and have write privileges to
the chosen directory.
Directory: [/home/william/Desktop/RealPlayer]: /home/william/RealPlayer/

You have selected the following RealPlayer configuration:

Destination: /home/william/RealPlayer/

Enter [F]inish to begin copying files, or [P]revious to go
back to the previous prompts: [F]: F

Copying RealPlayer files...No write-permission to /etc/profile.d ...skip.
.Succeeded.
installing application icons resource...
installing document icons resource...
..........Succeeded.
.Configuring Mozilla...
Installing .mo locale files...
Setting selinux context...
/usr/share or /usr/bin no write-permission...skip.

RealPlayer installation is complete.
Cleaning up installation files...
Done.


now ,you should goto the directory where you install the .bin .and run the realplayer in terminal.
like following:
william@william-superstar:~/RealPlayer$ ls
Bin common install.log mozilla postinst realplay RealPlayer11GOLD.bin
codecs doc LICENSE plugins README realplay.bin share
william@william-superstar:~/RealPlayer$ ./realplay

edit system file

graphical provide us the drag and drop ways to deal with files.but cause of the user permission control ,it always disappoint you.for example:u wanna move a file from /media/windowpartion to / .in command line ,it is no big deal .sudo mv /media/windowpartion / is enough.but if u wanna change graphically, maybe the popup alert will tell you: you request are denied. what we can do?
follow me :
if you are kde ,i mean ,kubuntu,type following command:
kdesudo konqueror
actually, here kongqueror is not a brower,but file manager system.now ,you can use it edit the file belongs to root.cause there is kdesudo when you run konqueror ,remenber?
if Ubuntu (Gnome)
gksudo nautilus
if dont take effect.type ATL+F2 and come into command mode,
then type:
gksudo nautilus
this would work
if Xubuntu (XFCE)
type :
gksudo thunar


at last but not least: Good luck!

Monday 30 June 2008

Vista Ubuntu grub Boot

It is a cool thing to install dual OS -windows and linux(or unix ).
As we know ,if u guy wanna install multi-boot systems ,u should first install windows and then linux. linux have 2 loader tools--lilo and grub.Actually ,i prefer grub ,more powerful and flexibly.

Ok till now ,everthing goes fine .but if my windows crash down,and i reinstall it ,finnaly u find you the grub is missing and you have no choise but enter windows.
so how to reinstall grub when you windows wipe it out?
follow me!
first step:
insert your Ubuntu CD,then boot form live cd .i mean ,you run the option: "try ubuntu without any change to your computer".
after that you will enter ubuntu system.and open the terminal(console is also ok,hehe )
second step:
enter following commonds:
sudo grub
find /boot/grub/stage1
(then the output will be like this: (hd*,*) )
root (hd*,*)
setup (hd0)
quit


then restart your computer .congratulations!
ps:sometimes u also find the grub do not contains the windows items.so you should edit
/boot/grub/menu.lst(note:i donot do this in person ,if this donot work .check it out in google )
and add something like that:
# This entry automatically added by the Debian installer for a non-linux OS
# on /dev/sda1
title Microsoft Windows XP Home Edition
root (hd0,0)
savedefault
makeactive
chainloader +1



双系统,windows崩溃,重装系统后 grub启动菜单丢失此时修复的方式为:
1 插入光盘(如果没有光盘的话那就有点困难了)
2 以 live cd 方式启动,进入系统(如果你的系统是8.0的那么就是第一个选项)
3 打开终端输入下面的命令
sudo grub
find /boot/grub/stage1
4然后会有这样的输出:(hd*,*)
5接着输入下面的命令:
root (hd*,*) 注:也就是上面的输出
setup (hd0)
quit
6重启之后就可以进入Ubuntu 了
PS:优势发现无法进入windows。此时可以在 /boot/grub/menu.lst 加入如下内容
(这个我没有亲手试过,如果不行可以再在google上看下)

# This entry automatically added by the Debian installer for a non-linux OS
# on /dev/sda1
title Microsoft Windows XP Home Edition
root (hd0,0)
savedefault
makeactive
chainloader +1

Sunday 29 June 2008

Ubuntu Resolution

you know what ? this damn problem really piss me off .
and finally i fix it.
problem: the max resolution is 800*600
reason:nvidia (if this is your video card type),you should manually install it . find the
hardware item ,and then choose enable it .then have a cup of coffee,Ubuntu will do the rest ........
Hulla

Sunday 25 May 2008

hibernate configuration

when you config hibernate application,make sure you have import the following 9 jars:
c3p0.jar,cglib.jar,commons-collection.jar,dom4j.jar,commons-logging,jar
asm.jar,antlr.jar.actually,the names of the jars is not precise.no version.but it is ok.
then you should config the configuration files.hibernate.cfg.xml,log4j.properties,and *.hbm.xml

Friday 4 April 2008

3ds max 在vista中局部黑屏的解决方法

下载autodesk公司专门为解决与vista兼容的sp2补丁包:http://usa.autodesk.com/adsk/servlet/ps/index?siteID=123112&id=5585571&linkID=9241177

3ds Max compatibility with vista

sometimes after you install the 3ds max 9.0 in vista ,you will find the it turns black in some region in max interface .it really annoy you,but it seems you can do nothing to fix this problem .
in fact,autodesk have resolve this.you can download the sp2 which is developed for vista(address:http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=9593622&linkID=9241177)then install it .
ok ,good luck.
ps:make sure the sp2 you have downloaded match your version.