Archive for 02月, 2010

用perl脚本解决ant…非法字符:\65279…的问题

Feb 21 2010 Published by Tony under Java,Perl

用perl脚本解决ant…非法字符:\65279…的问题


用ant管理项目,编译时发现有些utf8编码的java文件无法编译,
报错是…非法字符:\65279…。

在网上查N多与ant有关的文章,但是大多数的解决方案都不是很理想。因为文件比较多,而且我的
机器上也没有装editplus。
索性自己用perl写了一个脚本
如下:

#remove the utf-8  BOM for Ant
sub remove_bom {
	#open( my $in, "+<", "src/com/umpay/wap20/mobileProxy/MobileProxy.java" );
	foreach my $filename (@_) {
		print $filename,"\n";
		open( my $in, "+<", $filename );
		@lines = <$in>;
		$line1 = $lines[0];
		$t_chk1 = substr( $line1, 0, 1 );    #0xef -> 239
		$t_chk2 = substr( $line1, 1, 1 );    #0xbb -> 187
		$t_chk3 = substr( $line1, 2, 1 );    #0xbf ->191
		if ( ord($t_chk1) == 239 && ord($t_chk2) == 187 && ord($t_chk3) == 191 )
		{
			$line1 = substr( $line1, 3 );
			seek( $in, 0, 0 );
			print $in $line1;
		}
		close $in;
	}
}
&remove_bom("src/com/umpay/wap20/mobileProxy/MobileProxy.java"
,"src/com/umpay/wap20/security/GeneralKeyPairs.java"
,"src/com/umpay/wap20/security/RSAUtil.java"
,"src/com/umpay/wap/pages/WML.java");

其中remove_bom方法就是处理有问题的文件的方法。
把你的项目中出现问题的文件名称一个一个的放到remove_bom的参数列表中就可以了。ant,BOM,ant,BOM
最后运行这个perl文件。之后再运行ant就可以了。

No responses yet

perl入门之语法及数据类型

Feb 19 2010 Published by Tony under Perl

这次春节回家,什么资料也没带,刚好机器里也没什么东东,只有之前装的perl,索性翻了翻perl的文档,发现和ruby最相似的语言原来是perl,应该是ruby抄袭的perl。
Perl的语法要求:每一句后最后都要有分号,最后一句可以省略分号。

Perl 的数据类型包括:Scalars,arrays,hashes
Scalar:就是变量
Scalar 值可以是字符串,整形或者浮点型。Perl会自动转型,换句话说,perl是若类型语言。但是如果你要定义一个变量,需要使用my这个关键字。使用起来也极其简单。
Scalar values can be used in various ways:

my $animal = "camel";
    my $answer = 42;
    print $animal;
    print "The animal is $animal\n";
    print "The square of $answer is ", $answer * $answer, "\n";

一般脚本语言都会预定义一些变量。如果你用过ruby或者python,那你一定深有体会。
在perl中也有一些预定义的变量,比如$_就是预定义值。
试一下这两句,你就知道了。

$_="test";
print;

说实话,这种预定义的特性,对于System Administrator来说是一个好用的属性,但是对于Developer来说,真是很痛苦的一个特性。
Array:就是数组

    my @animals = ("camel", "llama", "owl");
    my @numbers = (23, 42, 69);
    my @mixed   = ("camel", 42, 1.23);
 
    print $animals[0];              # prints "camel"
    print $animals[1];              # prints "llama"
  $#array 为最后一个数组元素的下标。例如:
    print $mixed[$#mixed];       # last element, prints 1.23

之前就听说perl的语法及其诡异,但是当我真正用的时候,才发现太诡异了。看下面两句:

if (@animals < 5) { ... }#这一句可以判断@animals中元素的个数。
print @animals;#这一句会打印出@animals中的所有元素。

还有下面这个,和ruby很相似的“范围”语法

  @animals[0,1];                  # gives ("camel", "llama");
    @animals[0..2];                 # gives ("camel", "llama", "owl");
    @animals[1..$#animals];         # gives all except the first element

This is called an “array slice”.
You can do various useful things to lists:

    my @sorted    = sort @animals;
    my @backwards = reverse @numbers;

当然,这里还有很多特殊的数组, 比如@ARGV(the command line arguments to your script) 还有@_(the arguments passed to a subroutine). 后面会有单独的文章介绍。
Hashes
不多说了,一种键值对的数据结构,附带说两句,其实这个数据结构名叫哈希,其实并不是我们熟悉的hash数据结构,因为正统的hash结构其键值之间应该有一种字面意义上的对应关系,特别是应该有一种hash key 生成体制。Perl中的hash没有这个设计。:

    my %fruit_color = ("apple", "red", "banana", "yellow");
You can use whitespace and the => operator to lay them out more nicely:
    my %fruit_color = (
        apple  => "red",
        banana => "yellow",
    );
#To get at hash elements:
    $fruit_color{"apple"};           # gives "red"
#You can get at lists of keys and values with keys() and values().
my @fruits = keys %fruit_colors;
my @colors = values %fruit_colors;

如果要使用hash中的一个元素,则用$符号,如果使用整个hash则使用%符号。例如:

Print $fruit_color{"apple"};           # gives "red"
my @fruits = keys %fruit_colors;

变量作用域:
定义一个变量有两种方式,分别为一下两行:

    my $var = "value";
    $var = "value";

但是,第二行定义的变量将是一个全局变量,而第一行创建的变量是block级别的变量,这一点和JavaScript的语法非常相似。
如下:

    my $x = "foo";
    my $some_condition = 1;
    if ($some_condition) {
        my $y = "bar";
        print $x;           # prints "foo"
        print $y;           # prints "bar"
    }
    print $x;               # prints "foo"
    print $y;               # prints nothing; $y has fallen out of scope

条件语句:
这个与ruby几乎一摸一样:

If与unless
    if ( condition ) {
        ...
    } elsif ( other condition ) {
        ...
    } else {
        ...
    }
unless:
    unless ( condition ) {
        ...
    }

当然也可以写在一行:

print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;

普通循环:

    while ( condition ) {
        ...
    }
    until ( condition ) {
        ...
    }
    print "LA LA LA\n" while 1;          # loops forever

for循环

for ($i = 0; $i <= $max; $i++) {
        ...
    }

foreach循环
看例子:

#Hash:
my %fruit_color=("apple"=>"red","banana"=>"yellow");
foreach my $key(keys %fruit_color){
	print "The value of $key is $fruit_color{$key}","\n";
}
#Array:
my @fruit_arr=("apple","banana","capp","del");
foreach (@fruit_arr){
	print $_,"\n";
}
 
foreach my $i(@fruit_arr){
	print $i,"\n";
}
#还可以写到一行,类似于ruby的语法:
print $_,"\n" foreach (@fruit_arr);
#还可以使用范围:
#比如:
print $list[$_] foreach 0 .. $max;

perl中的变量都是预定义的变量
比如

my $a="";#如果是字符串类型的变量,””等同于false,其他是true
if($a){
print "true";
}else{
print "false";
}
my $a=0;#如果是数字类型的变量,0等同于false,其他是true
if($a){
print "true";
}else{
print "false";
}

my $b;#如果你定义一个变量,没有赋值,那么当你对它操作的时候会自动赋值,如果需要变量为数字型,就赋值为0,如果需要是字符串型,则赋值为””。
$b++;
print($b);

No responses yet

SIP Servlet入门教程及例子

Feb 19 2010 Published by Tony under Java

作为一个SIP Servlet Tutorial,这个文档主要描述了在JavaEE平台下如何开发基于SIP协议的应用服务。当然这个教程也包含了如何将JavaEE技术与SIP应用程序集成。
这个教程主要涉及到的软件有:
1. JavaSE 5.0
2. Glassfish and Sailfin(这是目前为止,我知道的唯一的一个开源的java sip servlet 容器)
3. Netbeans IDE(主要是在sailfin的安装包中有Netbeans的插件,所以使用NB)
4. X-Lite Soft Phone 或者MyFreesipphone
5. Apache Ant
这里就不多介绍SIP协议了,直接进入主题。
熟悉web开发的人基本都知道Http request 和 http Response 两个对象。
对应的,SIP也有对应的对象。
SIP Request
常见SIP Request Action

  • INVITE 请求初始化一个session
  • ACK 回应INVITE请求,是(acknowledges的简写)
  • BYE 请求关闭连接
  • CANCEL 取消所有未处理的action,但是不释放连接
  • REGISTER 向服务器注册一个地址,或者说,客户端向服务器发送一个注册请求


  • 什么是SIP Servlets?
    SIP Servlet 是一个 基于Java 语言的 server-side 组件,就类似于Java Servlet 一样,只不过SIP Servlet 需要运行在 SIP Servlet 容器中。
    而且SIP Servlet主要用来处理SIP请求,而Servlet用来处理HTTP请求。
    HTTP Servlet 与 SIP Servlet的不同之处:
    1. HTTP Servlet 都会有一个context对象,也就是每个Servlet都有一个上下文的概念。而SIP Servlet没有。
    2. HTTP Servlet 通常会返回一个HTML 页面或者某种形式的字符串(比如JSON),而SIP请求通常只是起到连接服务器与客户端的作用。
    3. SIP 是一个P2P的协议,所以服务器端同样可以向客户端发送SIP请求。
    4. SIP Servlet通常只是扮演一个代理的角色,最终的请求(客户端的请求)会发送到另一个已注册的SIP客户端。而HTTP Servlet会返回给客户端一个HTTP response。
    5. SIP协议类似于长连接,但是一个无状态的链接,所以它可以返回个客户端多个相互独立的response,而HTTP是一个无状态的协议,一个Request对一个Response。
    6. SIP 请求可以是一个异步的请求。这一点取决于上一个特性。
    关于SIP Servlet的annotation。
    Annotation 描述
    @SipServlet 标示这是一个SIP Servlet
    @SipListener 标示这个一个Sip Listener
    @SipApplication 用来定义一组SIP Servlets
    @SipApplicationKey 为一个SIP请求或者一个SIP session分配一个SipApplicationSession
    比如:

    @SipServlet
    public class MyServlet extends SipServlet{}

    @SipApplication 这个注释一般都用在包上。
    比如

    @SipApplication(name=”MySipApp”)
    Package com.example.sip;

    而@SipApplicationKey这个注释需要使用在方法上,而且这个方法需要满足以下条件:
    1. Public method
    2. Static method
    3. Return a String
    4. 方法的参数必须是SipServletRequest 类型
    5. 传入的参数不可变
    例如:

    @SipApplication(name=”MySipApp”)
    Package com.example.sip;
     public class MySipApp{
    	@SipApplicationKey
    	public static String sessionKey(SipServletRequest request){
    		Return hash(request.getRequestURI()+getDomain(request.getForm()));
           }
    }

    在一个Sip application中只能有一个SipApplicationKey。
    SIP Factory
    SIP Factory 是一个Servlet Factory,也就是说所有的SIP请求进入SIP容器后,都要通过SIP Factory来创建一个Servlet实例。所以SIP Factory是整个SIP容器的入口。如果想调用容器中的其他资源,可以通过SIP Factory来调用。而调用的方法包括依赖注入和”查找”两种方式。
    看例子:

    //通过注释来调用
    @Resource
    SipFactory sf;
    //通过查找的方式
    SipFactory sf=(SipFactory)getServletContext().getAttribute(“javax.servlet.sip.SipFactory);

    SIP Session
    SIP协议是一个无状态协议,所以一个response只能对应一个request(虽然一个request可以对应多个response)。也就是说多个request之间无法共享数据。
    但是SIP Session提供了一种比较便捷的方式,用来存储request之间的共享数据。而这种方式非常类似于HTTP servlet中的Session对象。
    但是与HTTP Session不同的是,在SIP应用中还有一个SIP ApplicationSession对象,这个东西很强大,它可以关于整个应用的session信息。
    除此之外,还有个SipSessionUtil可以使用。使用方法和SIP Factory类似:

    @Resource
    SipSessionUtil sessionUtil;
    //或者
    SipSessionUtil sessionUtil=(SipSessionUtil)getServletContext().getAttribute(“javax.servlet.sip.SipSessionUtil);

    SIP Listeners
    SIP application Listeners 就是用来监听SIP相关事件的Java Servlet listeners。它需要实现SIPServletListener接口。同时在其类上标注上Annotation用于简化部署。
    比如:

    @SipListener
    Public class MyListener implements SipServletListener{
    …..
    }

    Back-to-Back User Agent Applications
    一个back-to-back user agent(B2BUA)本身就是一个应用程序,同时它还是一个工具,很类似于代理。用于将一个客户端请求,转发给另一个客户端。而javax.servlet.sip.B2buaHelper就是一个实现这种功能的帮助类。

    以上内容翻译自SUN的SIP Servlet Tutorial文档。
    下面是我自己写的一个简单的sip程序。

    package com.ohacker.sip.proxy;
    import java.io.IOException;
    import java.util.ArrayList;
    import javax.servlet.ServletException;
    import javax.servlet.sip.*;
    import javax.servlet.sip.Address;
    /**
     *
     * @author O!Hacker
     */
    @javax.servlet.sip.annotation.SipServlet
    public class RegistratorServlet extends javax.servlet.sip.SipServlet {
       public static ArrayList<Address> CLIENT_LIST=new ArrayList<Address>();
     
        @Override
        protected void doInvite(SipServletRequest req) throws ServletException, IOException {
            System.err.println("doInvite action: "+ req.getCallId());
            Proxy proxy=req.getProxy();
            System.err.println(req.getTo().getURI().toString());
            proxy.proxyTo(req.getTo().getURI());
        }
     
        @Override
        protected void doRegister(SipServletRequest req) throws ServletException, IOException {
            System.err.println("doRegister action: "+ req.getCallId());
            System.err.println("doRegister action: "+ req.getRequestURI());
            SipServletResponse resp=null;
            Address address=req.getTo();
            if(!RegistratorServlet.CLIENT_LIST.contains(address)){
                CLIENT_LIST.add(address);
            }
            System.err.println(CLIENT_LIST.size());
            resp=req.createResponse(SipServletResponse.SC_OK);
            resp.send();
        }
    }

    No responses yet

    Ant 小记

    Feb 19 2010 Published by Tony under Java

    Ant 小记
    传统的ant 打包的项目需要处理文件和路径。特别是烦人的classpath。Ant内置了很多处理文件和路径的数据类型。比如fileset和path
    Fileset可以枚举文件。
    比如:

    <fileset id=”source.fileset” dir=”src” includes=”**/*.java”/>

    其中id是一个引用。其他的操作,可以通过id引用的方式调用它。比如:

    <copy todir=”backup”>
    	<fileset refid=”source.fileset”/>
    </copy>

    javac
    Debugging info
    Javac中常用到的选项
    Debug=”true” or debug=”false” debu=”true” debuglevel=”lines,vars,source”
    Nowarn=”true” verbose=”true” verbose是一个有意思的选项,它会在编译的时候打印出一些编译信息。当然还有classpath。
    比如:

    <javac destdir="${build.classes.dir}" debug="true" verbose="true" srcdir="src">
    			<classpath refid="compile.classpath"/>
    </javac>

    Src也可以用子元素来表示
    比如:

    <javac destdir="${build.classes.dir}" debug="true" verbose="true">
    	<classpath refid="compile.classpath"/>
    	<src path=”src”/>
    </javac>

    如果源文件分散在多个目录中可以使用引用的方式
    比如:

           <path id="src.dir">
    		<pathelement path="src:conf"/>
    	</path>
    	<target name="mkdir">
    		<mkdir dir="${build.classes.dir}"/>
    	</target>
    	<target name="compile" depends="mkdir">
    		<javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    		</javac>
    	</target>

    还有一种方法,比较土
    例子:

    <javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    			<src path=”test”/>
    		</javac>

    但是需要注意的是src指的是一个目录。

    在path或者fileset这类标签中常常会遇到类似以”**/*.jsp”这样的匹配模式。下面就讲讲在如何匹配。这种匹配方式好像应该叫做wildcard路径匹配方式。是目前比较常见的3中路径匹配风格之一,(题外话,另两种是mod_rewrite风格和perl 正则风格的路径匹配)

  • “*”表示一个或多个字符
  • “?”表示一个字符
  • “**”表示零个或者多个目录
  • 如果以”/”or”\”结尾,那么就相当于”**”
  • 常见例子:
    **/*~ linux 下的备份文件
    **/CVS/ cvs元文件
    **/.cvsignore cvs文件
    **/.svn/ SVN元文件目录
    比如在javac中的使用

    <javac srcdir=”src” destdir=”build/classes”>
    	<include name=”org/mama/**/*.java”/>
    	<exclude name=”org/mama/papa/*.java”/>
    </javac>

    下面是一个完整的java 项目的build文件

    <?xml version="1.0"?>
    <project name="java_project" default="archive">
    	<property file="build.properties"/>
     
    	<path id="compile.classpath">
    		<pathelement location="lib/*.jar"/>
    	</path>
    	<path id="src.dir">
    		<pathelement path="src/java"/>
    		<pathelement path="src/conf"/>
    	</path>
    	<target name="init">
    		<mkdir dir="${build.classes.dir}"/>
    		<mkdir dir="dist"/>
    	</target>
    	<target name="compile" depends="init">
     
    		<javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    		</javac>
    	</target>
    	<target name="archive" depends="compile">
    		<jar destfile="dist/${project.name}.jar" basedir="build/classes"/>
    	</target>
    	<target name="clear" depends="init">
    		<delete dir="build"/>
    		<delete dir="dist"/>
    	</target>
    </project>

    对应的build.properties文件也很简单
    project.name=default
    build.classes.dir=build/classes

    No responses yet

    图片一张

    Feb 09 2010 Published by Tony under Life

    No responses yet

    Glassfish sip server(sailfin) install 安装glassfish sip server

    Feb 09 2010 Published by Tony under Java

    Glassfish sip server(sailfin) install 安装glassfish sip server
    第一步:安装JDK,Ant

    第二步:下载sailfin:下载地址

    第三步:如果你的机器上正跑着glassfish,先关掉。在你的下载目录下运行:

    >java -Xmx256m -jar filename.jar

    等解压完后,再运行

    >cd sailfin
    >ant -f setup.xml

    第四步:之后将生成的目录加进环境变量中的Path下。

    第五步:在环境变量中加入AS_ADMIN_USER 值为admin

    第六步:从新开一个cmd console,运行

    asadmin start-domain domain1



    第六步:在浏览器中打开http://localhost:4848/

    第七步:输入admin/adminadmin
    大功告成

    No responses yet

    Next »