2007年5月18日

搭建过程备注:
1. 虚拟机软件Vmware 8.0 Workstation,Windows 2008 Enterprise Server, Sql Server 2008 R2。
2. 俩个节点平台版本必须一致,都为企业版。
3. 与构建Windows 2003群集不同,不能使用vmware的共享磁盘机制。Windows 2008集群对存储要求很高,不支持SCSI硬盘做集群。
    本次使用starwind 5.4代替vmware的共享磁盘实现群集存储。
4. 搭建Windows集群需要3台虚拟机:2个节点+1台存储。
5. 搭建SqlServer 2008集群需要4替虚拟机:2个节点+1台DC+1台存储。

搭建顺序:
1. 安装DC+DNS服务器。
2. 安装集群节点, 配置双网卡,域登录。
3. 安装群集磁盘服务器
4. 在集群节点上配置iSCSI发起。
5. 在集群节点上安装“故障转移群集”功能。
6. 进行故障转移群集验证和创建。
7. 至此,Windows集群环境安装完毕。
8. 在集群节点上按群集方式安装SqlServer 2008。
9. SqlServer 2008集群环境构建完毕。

参考文档:
Windows Server 2008的故障转移群集入门: http://os.51cto.com/art/201007/210286.htm
windows server2008虚拟机+群集: http://wenku.baidu.com/view/5e5b2be8e009581b6bd9eb1a.html
Windows2008+sqlserver2008集群安装:http://wenku.baidu.com/view/601dc74d2b160b4e767fcf46.html

posted @ 2012-06-21 09:23 bluoy 阅读(3931) | 评论 (0)编辑 收藏

神一样的软件,膜拜ing...
连我这天生kernel iptable有缺陷的都能用。

当前版本:2.04.
还是个Open Source的,改天一定要好好观摩一番的。

posted @ 2011-09-28 15:55 bluoy 阅读(303) | 评论 (0)编辑 收藏

If you meet following errors below when you try to build your source code:

 

Checking build tools versions...

build/core/main.mk:72:

************************************************************

build/core/main.mk:73: You are attempting to build on a 32-bit system.

build/core/main.mk:74: Only 64-bit build environments are supported beyond froyo/2.2.

build/core/main.mk:75:

************************************************************

Don’t panic, just change the code:

build/core/main.mk

ifeq ($(BUILD_OS),linux)

build_arch := $(shell uname -m) 

---ifneq (64,$(findstring 64,$(build_arch))) 

+++ifneq (i686,$(findstring i686,$(build_arch)))

 

and change the code in four mk files below from “+=-m64” to “+=-m32”


external/clearsilver/cgi/Android.mk

external/clearsilver/java-jni/Android.mk

external/clearsilver/util/Android.mk

external/clearsilver/cs/Android.mk


LOCAL_CFLAGS += -m32

LOCAL_LDFLAGS += -m32

end.

posted @ 2011-01-07 10:54 bluoy 阅读(356) | 评论 (0)编辑 收藏

I got this idea when i was surfing the web in search of a tool similar to the Nokia Pc Suite for my Linux

This How-To  works with many NOKIA Mobile Phone, especially for Nokia 3230, 6670, 6680, 6682 e 7610, 6120, Sony Ericsson Z1010, LG U8110/8120.

First of all, we have to grant access for Mobile Phone to “dialout” group.

sudo gedit /etc/udev/rules.d/40-permissions.rules

Now we have to add to the end of file:

# NOKIA 6120
BUS==”usb”, SYSFS{idVendor}==”0421″, SYSFS{idProduct}==”002f”, GROUP=”dialout”

where 0421 and 002f could be different depending on your Mobile Phone.
To check your idVendor and idProduct, we have to type on terminal

lsusb
Bus 003 Device 009: ID 0421:002f Nokia Mobile Phones

Now, we have to reload udev permission file:

sudo /etc/init.d/udev restart

We have to add our username on group “dialout”

gpasswd -a username dialout

All basics configurations for USB Data Cable are completed. We can start installation of obexftp and obextool GUI. Obextool GUI is written for tk graphic library, so GUI not have a good design as GTK.

sudo apt-get install openobex-apps libopenobex1 obexftp obextool

If you want start obextool from terminal we have to type for the first time:

export OBEXCMD=”obexftp -t /dev/ttyACM0 -u 1″
obextool

or, we can start it simply by typing:

obextool –obexcmd “obexftp -t /dev/ttyACM0 -u 1″

When we start Obextool we can see this error message:

It seems, that your device does not support the memory status feature.
Memory status will be disabled

To solve this problem we have to set some values on obextool.cfg:

sudo gedit /etc/obextool.cfg

set ObexConfig(config,memstatus) 0
set ObexConfig(config,filemove) 0

Another error message that we can see is:

FIle ‘/FileName/’ could not be uploaded to ‘E:/Path’!
Please check your file permissions.

To solve it:

sudo gedit /etc/obextool.cfg

set ObexConfig(config,dir_slash) 1

Good Job! Now your Mobile Phone works well in Ubuntu Gutsy with ObexTool.
If we want add it as Desktop Entry:

sudo gedit /usr/share/applications/obextool.desktop

[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Exec=/usr/bin/obextool –obexcmd “obexftp -t /dev/ttyACM0 -u 1″
Icon=/usr/share/icons/gnome/scalable/devices/phone.svg
Terminal=false
Name=Obextool
GenericName=
Comment=Browser your Mobile Phone
Categories=Application;Utility;

So, you can find it in your Gnome Panel over: “Applications” -> “Accessories” -> Obextool

posted @ 2009-04-23 16:30 bluoy 阅读(371) | 评论 (0)编辑 收藏

下面的例子实现把一个整数的各个位上的数字相加,通过这个例子我们再次理解 connect by.

create or replace function f_digit_add(innum integer) return number
is
outnum integer;
begin
if innum<0 then
return 0;
end if;
select sum(nm) into outnum from(
select substr(innum,rownum,1) nm from dual connect by
rownum<length(innum)
);
return outnum;
end f_digit_add;
/

select f_digit_add(123456) from dual;

posted @ 2009-04-01 17:02 bluoy 阅读(817) | 评论 (1)编辑 收藏

终于搞明白了困惑很久的问题,罪魁祸首还是jdk啊。天杀的。
以下内容转自网络:

测试环境:Win2K Pro日文版,SUN J2SDK 1.5.0-beta2

经过测试,发现Shift_JIS和MS932编码的全角波浪线(“~”)的编码都是 0x8160(16进制,两个字节,高位在前)。通过sun.io.ByteToCharMS932转换后得到Unicode字符'\uFF5E',而通过sun.io.ByteToCharSJIS转换后则得到Unicode字符'\u301C'。

反之,Unicode字符'\uFF5E'通过sun.io.CharToByteMS932转换后会得到MS932编码的本地字符0x8160(16进制,两个字节,高位在前),而Unicode字符'\u301C'通过 sun.io.CharToByteSJIS转换后也会得到Shift_JIS编码的本地字符0x8160(16进制,两个字节,高位在前),两者的转换结果相同。

结论:在WinNT/2K/XP上,MS932和Shift_JIS这两种本地字符集完全相同,只是分别采用JDK的sun.io.ByteToCharMS932和sun.io.ByteToCharSJIS对个别特殊的本地字符进行转换后所得到的 Unicode字符并不一样。实际上,MS932就是WinNT/2K/XP上的Shift_JIS,只是与标准版的Shift_JIS字符集相比,MS932收录了更多的字符,比如NEC和IBM对Shift_JIS的扩展(如日文中的“㊤㊥㊦㊧㊨①..⑳...”等等);然而,JDK中的 ByteToCharSJIS及CharToByteSJIS却使用了标准的Shift_JIS字符集,所以部分扩展字符在从byte转换成char或是从char转换成byte时会出现乱码,这的确是JDK让人非常迷惑的一处。

参考资料1(日文):http://www.asahi-net.or.jp/~ez3k-msym/charsets/jis2ucs.htm

posted @ 2009-02-03 16:52 bluoy 阅读(1378) | 评论 (0)编辑 收藏

1. 函数的overwrite实现时,函数参数类型必须严格一致。与overload不同,并不遵守参数优先匹配的原则。
所以,不能用子类,或这接口的实现类来妄图得到overwrite的目的。
2. 使用反射手法时,getMethod()的调用,参数类型必须与要得到的函数类型严格一致。与overload不同,并不遵守参数优先匹配的原则。
3内部类,要实例化时必须首先实例化包含类。可以理解为内部类只是包含类的数据成员
4非public类,非javabean规范的Bean,内部类BeanUtil类无法进行操作,比如clone()等等。

posted @ 2008-12-28 10:54 bluoy 阅读(180) | 评论 (0)编辑 收藏

虽然java没有提供函数指针的操作,而是必须通过对象来曲线救国。
不过延伸一下这个思路,其实也未必不是件好事。从某种意义上来说,整个java系统,或者对象系统,其实就是不计其数的钩子组成的系统。因为,参数传递的过程中完全依赖着对象,一种行为和数据的结合体。这里,关键词是参数传递和对象的行为,当然离不开多态。
        改变既有代码的行为步骤:
        1. 派生参数类得到新的子类。
        2. 在子类中覆写(overwrite)父类既有方法。
        3. 将子类的实例作为参数传递。
        这样,就得到了改变父类行为的目的。
 对于既有框架自作主张的封装,阻碍自己的目的的时候,这个做法往往能独辟蹊径。

posted @ 2008-12-28 10:40 bluoy 阅读(184) | 评论 (0)编辑 收藏

Spring Framework 的理解以及可维护性是否得以改善的思考

Spring的特性:
1. 提供了一种管理对象的方法,可以把中间层对象有效地组织起来。一个完美的框架“黏合剂”。
2. 采用了分层结构,可以增量引入到项目中。
3. 有利于面向接口编程习惯的养成。
4. 目的之一是为了写出易于测试的代码。
5. 非侵入性,应用程序对Spring API的依赖可以减至最小限度。
6. 一致的数据访问介面。
6. 一个轻量级的架构解决方案。

对Spring的理解
Spring致力于使用POJOs来构建应用程序。由框架提供应用程序的基础设施,将只含有业务逻辑的POJOs作为组件来管理。从而在应用程序中形成两条相对独立发展的平行线,并且在各自的抽象层面上延长了各自的生命周期。

Spring的工作基础是Ioc。Ioc将创建对象的职责从应用程序代码剥离到了框架中,通常2中注入方式:setter 和 ctor参数。
每个Bean定义被当作一个POJO(通过类名和JavaBean的初始属性或构造方法参数两种方式定义的Bean)。
Spring的核心在org.springframework.beans,更高抽象层面是BeanFactory. BeanFactory是一个非常轻量级的容器。

关于可维护性的思考
Spring之类的技术确实带来了应用系统的可维护性的提高吗?
Ioc, AOP之类的技术,本质上都是将原本位于应用程序代码中"硬编码"逻辑,剥离出来放到了配置文件中(或者其他形式)。主流声音都是认为提高了应用程序的可维护性。

但如果从以下方面观察,结合项目实际经验,个人感觉这些技术的应用大大降低了应用程序的可维护性,尤其是面对一个陌生的系统,或者项目人员变动频繁的时候。
1. 中断了应用程序的逻辑,使代码变得不完整,不直观。此时单从Source无法完全把握应用的所有行为。
2. 将原本应该代码化的逻辑配置化,增加了出错的机会以及额外的负担。
3. 时光倒退,失去了IDE的支持。在目前IDE功能日益强大的时代,以往代码重构等让人头痛的举动越来越容易。而且IDE还提供了诸多强大的辅助功能,使得编程的门槛降低很多。通常来说,维护代码要比维护配置文件,或者配置文件+代码的混合体要容易的多。
4. 调试阶段不直观,后期的bug对应阶段,不容易判断问题所在。
5. 性能问题。虽说硬件性能日新月异,但是性能也是在不经意间一点一点地流失的。从汇编到高级语言,到面向对象,到虚拟机,一直处于这样的发展趋势。

posted @ 2008-07-06 10:21 bluoy 阅读(2000) | 评论 (3)编辑 收藏

项目中组员偶然写了一段垃圾的sql语句,不想却误打误撞的发现了一个jdbc的bug,包括Oracle 10g附带的版本。

详细描述可以参考如下代码:
   public static void testSetTimestampBug() throws Exception{
        Calendar calendar = new GregorianCalendar();
        Date d = calendar.getTime();
        
        String sql = "select 1+1 from dual where ?-sysdate<1";         //error sql
        String sql1 = "select ?-sysdate from dual";                          //no error sql
        String sql2 = "select 1+1 from dual where ?-1<sysdate";       //no error sql
        PreparedStatement pst = cn.prepareStatement(sql);
        //pst.setDate(1, new java.sql.Date(d.getTime()));                 //no  error
        pst.setTimestamp(1, new java.sql.Timestamp(d.getTime()));   //bug!!!, throw SQLException: ORA-00932
    }
三种sql的写法中,第一种写法在使用setTimestamp()时会出错,其他俩种却不会有问题。
即正常调用PreparedStatement.setTimestamp()方法,遇到某些特殊写法的sql语句却会出错。
本例中,抛出如下例外:
java.sql.SQLException: ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL.
然而,如果使用setDate()方法,则一切正常,三种写法都没有问题。

因为有这个问题,如果在持久层使用了其他的中间件,则这个问题可能变的更加隐蔽,比如iBatis中的处理是这样的:
java.util.Date ---> ibatis.DateTypeHandler----->PreparedStatement.setTimestamp() 
java.sql.Date ---> ibatis.SqlDateTypeHandler----->PreparedStatement.setDate()
如果不注意输入参数类型的话,就会遇到上述问题。我就因此费了不少周折。
对于iBatis的使用建议,保证入口参数类型始终为java.sql.Date即可。

posted @ 2008-03-26 17:17 bluoy 阅读(1781) | 评论 (0)编辑 收藏

Web架构特性及REST架构风格(部分内容摘自网络)

良好的Web架构风格:
    1. 客户/服务器模式:  实现了UI与数据的分离。
    2. 服务端无状态性: 可见性,可靠性,可伸缩性等方面的改善。
     可见性-无状态性使得服务器不必要维护海量的上下文(Context)。
     可靠性-无状态性减少了服务器从局部错误中恢复的任务量。
     可伸缩性-无状态性使得服务器可以很容易的释放资源。
    3. 缓存: 减少服务端不必要的处理。
    4. 可伸缩性: 便于分布式和集群部署。
     上面的2,3点也是影响4的主要因素。而随着系统用户规模的指数上升,可伸缩性将变的至关重要。

现在大多数应用程序都忽略或者违反了上述2, 3的风格。当然也肯定失去了4带来的好处。
比如Java Servlet中HttpSession的应用,使服务器端保存了客户端的状态。
时下流行的动态页面的做法也使得资源缓存变得困难或者不可能。
这些都直接影响了应用的可伸缩性。

改善现状的思路是,把服务端的处理和状态前移,由客户端来实现。使服务端回归到无状态的特性。
以采用ajax技术的应用系统为例:因为不需要完全刷新就可以与服务器进行交互,使得有状态客户机成为可用选择。基于浏览器的应用程序代码可以在必要时获取新的服务器数据,并把这些数据织入当前页面。
将处理和状态前移到每个客户机上后,实现了无状态的服务端;同时缓存服务器可以缓存ajax引擎(比如dojo, prototype etc.),以及状态无关的数据。
个人理解,多种浏览器的plug-in技术(Sun的applet, MS的ActiveX等等),都应该是这种思路的不同技术实现。

经过以上分析整理,实际上已经涉及到了时下流行的一个概念-REST.

REST(Representational State Transfer)来源于Dr. Roy Thomas Fielding,  <Architectural Styles and the Design of Network-based Software Architectures>
当浏览器浏览访问一个url资源时,返回的页面即为该url资源的representation,这个representation给浏览器一个state,当
浏览器访问下一个url资源时,浏览器的state就transfer了。
REST其本身只是为分布式超媒体系统(distributed hypermedia systems)设计的一种架构风格,而不是某个标准,框架。

REST的设计准则
    1.网络上的所有事物都被抽象为资源(resource);
    2.每个资源对应一个唯一的资源标识符(resource identifier);
    3.通过通用的连接器接口(generic connector interface)对资源进行操作;
    4.对资源的各种操作不会改变资源标识符;
    5.所有的操作都是无状态的(stateless)。

REST中的资源所指的不是数据,而是数据和表现形式的组合。
REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现。以往的Web开发大多数用的都是Http协议中的GET和POST方法,对其他方法很少使用,这实际上是因为对Http协议认识片面的理解造成的。Http不仅仅是一个简单的运载数据的协议,而是一个具有丰富内涵的网络软件的协议。他不仅仅能对互联网资源进行唯一定位,而且还能告诉我们如何对该资源进行操作。Http把对一个资源的操作限制在4个方法以内:GET, POST,PUT和DELETE,这正是对资源CRUD操作的实现。由于资源和URI是一一对应的,执行这些操作的时候URI是没有变化的,这和以往的 Web开发有很大的区别。正由于这一点,极大的简化了Web开发,也使得URI可以被设计成更为直观的反映资源的结构,这种URI的设计被称作 RESTful的URI。这位开发人员引入了一种新的思维方式:通过URL来设计系统结构。当然了,这种设计方式对一些特定情况也是不适用的,也就是说不是所有的URI都可以RESTful的。
REST 之所以可以提高系统的可伸缩性,就是因为它要求所有的操作都是无状态的。由于没有了上下文(Context)的约束,做分布式和集群的时候就更为简单,也可以让系统更为有效的利用缓冲池(Pool)。并且由于服务器端不需要记录客户端的一系列访问,也减少了服务器端的性能。

posted @ 2008-03-24 16:35 bluoy 阅读(392) | 评论 (0)编辑 收藏

       Java语言编程中更新XML文档的四种方法。第一种方法是直接读写XML文件。第二种方法是使用Apache Crimson的XmlDocument类,这种方法极为简单,使用方便,如果你选用Apache Crimson作为XML解析器,那么不妨使用这种方法,不过这种方法似乎效率不高(源于效率低下的Apache Crimson),另外,高版本的JAXP或者是Java XML Pack、JWSDP不直接支持Apache Crimson,亦即这种方法不通用。第三种方法是使用JAXP的XSLT引擎(Transformer类)来输出XML文档,这种方法也许是标准的方法 了,使用起来十分灵活,特别是可以自如控制输出格式,我们推荐采用这种方法。第四种方法是第三种方法的变种,采用了Xalan XML Serializer,引入了串行化操作,对于大量文档的修改/输出有优越性,可惜的是要重复设置XSLT引擎的属性和XML Serializer的输出属性,比较麻烦,而且依赖于Apache Xalan和Apache Xerces技术,通用性略显不足。除此之外,实际上应用别的API(比如dom4j、JDOM、Castor、XML4J、Oracle XML Parser V2)也有很多办法可以更新XML文档。

概念介绍
        Xerces/Crimson是XML解析器,Xalan是XSLT处理器,xml-apis.jar实际上是JAXP。
        Apache Crimson的前身是Sun Project X Parser, 至今Apache Crimson的很多代码都是从X Parser中直接移植过来的。早期的JAXP是和X Parser捆绑在一起的。后来的 JAXP和Apache Crimson捆绑在一起,比如JAXP 1.1。最新的JAXP 1.2 EA(Early Access)改弦更张,采用性能更好的Apache Xalan和Apache Xerces分别作为XSLT处理器和XML解析器,不能直接支持Apache Crimson了。
        dom4j(dom4j.jar)是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。

posted @ 2008-03-19 10:27 bluoy 阅读(1980) | 评论 (0)编辑 收藏

.NET垃圾收集器的过去、现在和未来(一)

Patrick Dussud介绍:
Patrick Dussud在微软工作了11年,曾经负责VBA、Jscript、MS Java等语言运行时的垃圾收集器(Garbage Collector)的设计,目前负责.NET CLR垃圾收集器的设计。他是.NET CLR的架构师,WinFX的首席架构师,Windows架构师组的成员。
在微软之前,Patrick是德州仪器(TI)Explorer工作站系统的主要设计人,Lucid公司Energize产品的首席架构师。

关键内容摘要

1. 微管理 / 内存的显式管理 ---  手动内存管理(new/delete)
        你必须保证在释放之前内存没有被别人使用,如果你把内存给了别人,往往你就不确定应该何时释放内存了。当你释放了内存,不知道别人正在使用这块内存时,就产生了程序崩溃的问题。所以,当你显式进行“new”和“delete”时,内存管理是一个复杂的问题,并且,此时你的代码不可组合。要么你必须确定对自己的内存有完全的控制,因此,要达到这种完全隔离的目的,你必须在将内存传递给别的模块时进行完全拷贝,这样,别的模块就只对这个完全拷贝的内存负责。要么你就得在某个地方形成对整个内存池的统一的管理,这就是自动化内存管理,这就是垃圾收集器的工作。

2. 对象终止器的调用时机由垃圾收集器决定,这些对象的析构函数被调用的先后顺序是无法预先确定的。提出了“关键终止化对象”的概念。当有一系列对象需要终止化时,关键终止化对象最后被终止化,直到上层对象干完工作前。

3.  工作机理: 垃圾收集器首先遍历所有的栈和静态变量,然后返回最初的树集。然后遍历树集对程序能够到达的每一个对象作标记。此时,我们就能逐个对象地检查内存,发现它被标记了,好的,留下。没有被标记?喔,我们有一个垃圾了。

4.  垃圾收集器的绝大部分速度和效率都来源于对回收策略的调整。通过保持内存紧凑,形成缓存本地化,页面本地化等等优势,很可能其效率甚至高于传统“new”和“delete” 操作,尤其是对于非常难以管理的服务器内存来说更是如此。

posted @ 2008-03-13 21:26 bluoy 阅读(340) | 评论 (0)编辑 收藏

如下代码:
class A{
    public void foo(){print("aaaaa");}
}

class B extends A{
    public void foo(){print("bbbbb");}
}

如果想通过B的实例化变量来调用被override的父类的方法foo():

B b = new B();

在C++中(VC 6)可以两种途径;
1.  ((A)b).foo();
2.  A a = B();

在java中类似做法则行不通,依然访问的是子类方法。
而且,在java中好像达不到这个目的。

posted @ 2008-03-06 10:34 bluoy 阅读(1061) | 评论 (3)编辑 收藏

web常用的功能性测试方法

      
        1. 页面链接检查:每一个链接是否都有对应的页面,并且页面之间切换正确。

        2. 相关性检查:删除/增加一项会不会对其他项产生影响,如果产生影响,这些影响是否都正确。

        3. 检查按钮的功能是否正确:如update、cancel、delete、save等功能是否正确。

        4. 字符串长度检查:输入超出需求所说明的字符串长度的内容,看系统是否检查字符串长度,会不会出错。

        5. 字符类型检查:在应该输入指定类型的内容的地方输入其他类型的内容(如在应该输入整型的地方输入其他字符类型),看系统是否检查字符类型,会否报错。

        6. 标点符号检查:输入内容包括各种标点符号,特别是空格、各种引号、回车键。看系统处理是否正确。

        7. 中文字符处理:在可以输入中文的系统输入中文,看会否出现乱码或出错。

        8. 检查带出信息的完整性:在查看信息和update信息时,查看所填写的信息是不是全部带出,带出信息和添加的是否一致。

        9. 信息重复:在一些需要命名,且名字应该唯一的信息输入重复的名字或ID,看系统有没有处理,会否报错,重名包括是否区分大小写,以及在输入内容的前后输入空格,系统是否作出正确处理。

        10. 检查删除功能:在一些可以一次删除多个信息的地方,不选择任何信息,按”delete”,看系统如何处理,会否出错;然后选择一个和多个信息,进行删除,看是否正确处理。

        11. 检查添加和修改是否一致:检查添加和修改信息的要求是否一致,例如添加要求必填的项,修改也应该必填;添加规定为整型的项,修改也必须为整型。

        12. 检查修改重名:修改时把不能重名的项改为已存在的内容,看会否处理,报错。同时,也要注意,会不会报和自己重名的错。

        13. 重复提交表单:一条已经成功提交的纪录,back后再提交,看看系统是否做了处理。

        14. 检查多次使用back键的情况:在有back的地方,back,回到原来页面,再back,重复多次,看会否出错。

        15. search检查:在有search功能的地方输入系统存在和不存在的内容,看search结果是否正确。如果可以输入多个search条件,可以同时添加合理和不合理的条件,看系统处理是否正确。

        16. 输入信息位置:注意在光标停留的地方输入信息时,光标和所输入的信息会否跳到别的地方。

        17. 上传下载文件检查:上传下载文件的功能是否实现,上传文件是否能打开。对上传文件的格式有何规定,系统是否有解释信息,并检查系统是否能够做到。

        18. 必填项检查:应该填写的项没有填写时系统是否都做了处理,对必填项是否有提示信息,如在必填项前加* 

        19. 快捷键检查:是否支持常用快捷键,如Ctrl+C Ctrl+V Backspace等,对一些不允许输入信息的字段,如选人,选日期对快捷方式是否也做了限制。

        20. 回车键检查:在输入结束后直接按回车键,看系统处理如何,会否报错。

posted @ 2008-01-11 09:55 bluoy 阅读(188) | 评论 (0)编辑 收藏

调整完/usr的挂载点后,出现了一个奇怪的现象,原来正确的系统时钟现在出故障了,提前了8个小时。
鼓掌现象具体表现为:每次启动系统,ubuntu会用BIOS的时间+8后作为系统时钟,同时会把新的时间重新同步到BIOS中。所以每启动一次,时间就会快进8小时。很是怪异。
网上一通google才搞定。

原因是因为/usr的挂载时间被滞后了,由于/etc/localtime(时区信息)是连接到/usr/share/zoneinfo/下的某个设定好的时区文件。在系统获取时区信息时/usr尚未挂载,所以系统始终就错了。

修复办法很简单:
1.  rm /etc/localtime(取消原来的符号连接)
2. 把/usr/share/zoneinfo/下的某个设定好的时区文件copy到/etc/localtime.
3. 重新启动,故障消除。

相关概念:
UTC(Universal Time Coordinated)  = GMT  (Greenwich Mean Time)
hwclock :   query and set the hardware clock (RTC)
hwclock通过/etc/default/rcS的UTC(=yes/no)来认定BIOS时钟是UTC还是localtime。

参考文章:
http://blog.chinaz.com/u1/5830/archives/2006/36628.shtml

posted @ 2007-11-13 12:09 bluoy 阅读(283) | 评论 (0)编辑 收藏

昨天由于ubuntu的/分区空间紧张,决定把/usr挂载到别的分区。
挂载步骤(root权限执行):
1.   init  1  -- 切换到单用户模式。
2.   cp -ax /usr/*  /mnt/tmp  (tmp为新的/usr分区)。 -- 拷贝现在/usr下的内容到待切换的分区。
3.   ls -l /dev/disk/by-uuid    -- 查看分区的UUID。
4.   修改/etc/fstab中/usr的挂载方式,挂接到新的/usr分区。
5.   mv /usr /usr.old   -- 重命名现有的/usr为/usr.old, 为第6步做准备,重启动后可以删除之。
6.   mkdir /usr   -- 创建新的/usr挂载点,启动时自动挂载/usr分区到此处。
7.   restart

posted @ 2007-11-13 11:49 bluoy 阅读(5723) | 评论 (5)编辑 收藏

/home 分区是最常移动的分区之一。某些时候,/home 中的全部空间都用完了,而且需要增加一个硬盘驱动器。另一些时候,/home 被设置为根分区的一部分,为了提高性能或便于备份,可能需要将它移动到别的地方。我会针对每种情况说明如何安全有效地移动 /home。

please visit the address:
http://www.ibm.com/developerworks/cn/linux/l-tip-prompt/tip05/index.html

posted @ 2007-11-09 15:52 bluoy 阅读(142) | 评论 (0)编辑 收藏

网上常见的推荐是tora. 地址: http://sourceforge.net/projects/tora/
但由于License关系,二进制版本剔除了对oracle的providor. 所以需要下载源码自己编译。
感觉比较麻烦。

最近又找到一个比较好的东东-- Aqua Data Studio。 (http://www.aquafold.com/index.html)
而且也有免费版本。
下载试用了一下,非常方便易用。
推荐给有此需要者。

posted @ 2007-11-07 11:49 bluoy 阅读(2493) | 评论 (0)编辑 收藏

如何临时增加交换空间。

1.产生一个64M的空文件

#dd if=/dev/zero of=/swapfile bs=1024 count=65536

2.初始化该文件为交换文件:

mkswap /swapfile 65536

sync

3.激活这个交换文件:

swapon /swapfile

posted @ 2007-11-06 14:03 bluoy 阅读(295) | 评论 (0)编辑 收藏

The follow statement execute error using 9i driver(Oracle JDBC Driver version - 9.0.2.0.0).
throw UncategorizedSQLException(Invalid Column Type Exception), 
errorcode: 17004.
Upgrade to Oracle JDBC Driver version - 10.2.0.1.0, it is OK.

Example:

......
PreparedStatement pst = cn.prepareStatement("select sysdate from dual where 1=?");
pst.setNull(index,  java.sql.Types.NULL);   -------- throw exception!!
......




posted @ 2007-10-09 19:39 bluoy 阅读(905) | 评论 (0)编辑 收藏

Using the JDBC 8i, 9iR1, Oracle's DATE datatype is mapped to the "java.sql.Timestamp" class. However, the new "ojdbc14.jar" driver maps DATE to "java.sql.Date", and "java.sql.Date" only holds a date (without a time), whereas "java.sql.Timestamp" holds both a date and a time.




Subject: JDBC 920x Date/TimeStamp mapping
Type: BULLETIN
Status: UNDER_EDIT
Content Type: TEXT/PLAIN
Creation Date: 29-JUL-2003
Last Revision Date: 04-OCT-2004


PURPOSE
-------
   Clarify the use of oracle.jdbc.V8Compatible property flag
 
SCOPE & APPLICATION
-------------------
JDBC 920x Date/TimeStamp mapping is different from JDBC 8i, 9iR1.
<TITLE FOR MAIN ARTICLE TEXT>
-----------------------------
Summary of  features afftected by oracle.jdbc.V8Compatible.
 
As of 9.2.0.1.0 Oracle realigned its DATE type with the java.sql.Types.DATE type.
Prior to this
java.sql.DATE and  java.sql.TIMESTAMP were mapped to java.sql.Types.TIMESTAMP.
 
This mapping change applies to JDBC default mapping (i.e when getObject() is
used for Date column.
 
example:
select sysdate from dual;
...
while (rset.next ())  {
System.out.println("getObject for sysdate  : " +
rset.getObject(1).getClass().getName());
System.out.println("getDate for sysdate :" +
rset.getDate(1).getClass().getName());
System.out.println("getTimetamp for sysdate :" +
rset.getTimestamp(1).getClass().getName());
}
 
Prior to 9201, this will return
getObject for sysdate  : java.sql.Timestamp      <<<<
getDate for sysdate :java.sql.Date
getTimetamp for sysdate :java.sql.Timestamp
 
As of 9201 onward the following will be returned
 
getObject for sysdate  : java.sql.Date        <<<<<
getDate for sysdate :java.sql.Date            >> no change
getTimetamp for sysdate :java.sql.Timestamp   >> no change
 
 
 
Note: java.sql.Date has no time portion whereas java.sql.Timestamp does.
 
 
With this change in Datatype mapping, some application will fail and/or generate
incorrect results when JDBC driver is upgraded from 8i/ 9iR1 to 920x JBDC driver.
To maintain compatibility and keep applications working after upgrade, a compatibility flag was
Provided.  Developers now have some options:
 
1>
Use oracle.jdbc.V8Compatible flag.
 
JDBC Driver does not detect database version by default.
To change the compatibility flag for handling TIMESTAMP datatypes,
connection property 'oracle.jdbc.V8Compatible' can be set to
'true' and the driver behaves as it behaved in 8i, 901x, 9200
(with respect to TIMESTAMPs).
By default the flag is set to 'false'. In OracleConnection constructor
the driver obtains the server version and set the compatibility flag
Appropriately.
 
java.util.Properties prop = new java.util.Properties ();
prop.put ("oracle.jdbc.V8Compatible", "true");
prop.put ("user", "scott");
prop.put ("password", "tiger");
String url ="jdbc:oracle:thin:@host:port:sid";
Connection conn = DriverManager.getConnection (url,prop);
 
 
 
With JDBC 10.1.0.x, in instead of the connection property, the following system
property can be useed
java -Doracle.jdbc.V8Compatible=true .....
 
 
 
Note: This flag is a client only flag that governs the Timestamp and Date mapping.
It does not affect any Database feature.
 
 
 
2> use set/getDate and set/getTimestamp   when dealing with Date and TimeStamp column datatype accordingly.
9i server  supports both Date and Timestamp column types
 
DATE is mapped to  java.sql.Date and TIMESTAMP is mapped to java.sql.Timestamp
 
I> using setTimestamp
 
PreparedStatement pstmt = conn.prepareStatement(
"SELECT count(*) from  tstable where tscol between ? and ?");
// tscol of type Timetamp (or it can be Date)
 
String s = new String("2003-01-14 10:00:00.000000000");
Timestamp ts1 = Timestamp.valueOf(s);
pstmt.setTimestamp(1, ts1); // Timestamp
 
String s2 = new String("2003-01-16 10:00:00.000000000");
Timestamp ts2 = Timestamp.valueOf(s2);
pstmt.setTimestamp(2, ts2); // Timestamp
...
 
 
II>using setDate
 
PreparedStatement pstmt = conn.prepareStatement(
"SELECT count(*) from  tstable where datecol between ? and ?");
// datecole of type Date
 
/*
pstmt.setDate(1,new java.sql.Date(System.currentTimeMillis()));
pstmt.setDate(2,new java.sql.Date(System.currentTimeMillis()));
*/
 
SimpleDateFormat start_dt_in1 = new SimpleDateFormat("2002-09-18 00:00:00");
SimpleDateFormat start_dt_in2 = new SimpleDateFormat("2003-09-18 00:00:00");
pstmt.setDate(1,start_dt_in1);
pstmt.setDate(2,start_dt_in2);
 
 
 
Summary of  features afftected by oracle.jdbc.V8Compatible.
 
Is backward compatible (with oracle.jdbc.V8Compatible)?

 
 
* Examples:
..
The following will fail   when using JDBC 9iR1, 9iR2 connecting 817 server since the
817 did not support Timestamp
 
 
Connection conn = DriverManager.getConnection(url, "scott",  "tiger");
// Prepare a statement to cleanup the emp table
Statement  stmt = conn.createStatement();
try {
stmt.execute("delete from EMP where EMPNO = 1");
} catch (SQLException e) {
}
try {
stmt.execute("INSERT INTO EMP (EMPNO, ENAME, HIREDATE) VALUES (1, 
'ALI', {ts '2003-04-14 14:19:24.94'})");
} catch (SQLException e) {
e.printStackTrace();
}
 
Error : Exception in thread "main" java.sql.SQLException: ORA-00904: invalid column name
 
Solution you need
1> fix for Bug 2640192 (included in 9204)
2> oracle.jdbc.V8Compatible", "true"
 
 
 
In earlier versions of JDBC drivers  SQL FUNCTION "TS" was mapped to "to_date" .   So, the query
 
select {ts '2002-10-18 18:02:00'} from dual;
was translated by JDBC to,
select TO_DATE ('2002-10-18 18:02:00',  'YYYY-MM-DD HH24:MI:SS') from dual;
 
 
With 9i Timestamp is supported in the database and also by 9203 JDBC Drivers.
So the query
 
select {ts '2002-10-18 18:02:00'} from dual;
 
is now translated  by JDBC to
 
select TO_TIMESTAMP('2002-10-18 18:02:00', 'YYYY-MM-DD HH24:MI:.SS.FF') from dual;
 
 
Known issues:  There is some performances issue when set/getTimestamp
Bug 3037615
Bug 2770935
These bugs are very likely duplicate.
 
 
The following code will no longer work with 9203+ unless V8 flag is set to true
 
Timestamp start_dt_in = Timestamp.valueOf("2002-09-18 00:00:00");
Timestamp now_period_start_dt ;
PreparedStatement stmt = null;
ResultSet rs = null;
 
System.out.println("start_dt_in="+  start_dt_in );
 
try {
stmt = conn.prepareStatement( "SELECT TRUNC(?) FROM DUAL" );
stmt.setTimestamp( 1, start_dt_in );
rs = (OracleResultSet) stmt.executeQuery();
if ( rs.next() ) {
now_period_start_dt = rs.getTimestamp( 1 );
System.out.println("Curr Period Start="+  now_period_start_dt );
}
 
 
will generate
Exception in thread "main" java.sql.SQLException:
ORA-932: inconsistent datatypes
 
 
Reason : trunc ( )  supports Date columns and does not support  Timestamp  (this is an RDBMS issue).
So, you need to set the V8 flag to true
 
Another bug that changed the Date/Timetamp mapping is  2428427 to comly with
J2EE 1.3 CTS.  This was fixed in 9014 and it specific to classesdmx*.zip/jar
(the *dms* jar filed mainly used by iAS/OC4J).  These *dms* jar files, by the
default value for oracle.jdbc.J2EE13Compliant  is true.  in classes111.zip
classes12.jar and ojdbc14.jar/zip the default is false.
 
One can toggel this flag  true/false by
 
java -Doracle.jdbc.J2EE13Compliant=true|false
 
 
example of of sample runs:
 
query used :"select sysdate from dual"
classes12dms.jar used.
 
 
Driver Version      Object Type
==============      ===========
9.0.1.3.0         java.sql.Timestamp >> fix for 2428427 NOT included
9.0.1.4.0         java.sql.Date   >> fix for 2428427 INCLUDED
9.0.1.5.0         java.sql.Date   >> fix for 2428427 INCLUDE
 
In JDBC 9014+ ,to keep older (9013) behavior  simply run the application with
 
 
$java -Doracle.jdbc.J2EE13Compliant=false .....
 
 
However please note that J2EE 1.3 CTS require that Date to mapped to
java.sql.Date.

posted @ 2007-10-09 19:16 bluoy 阅读(1120) | 评论 (0)编辑 收藏

我们知道,在Struts 1.0中,我们只能在web.xml中为ActionServlet指定一个配置文件,这对于我们这些网上的教学例子来说当然没什么问题,但是在实际的应用开发过程中,可能会有些麻烦。因为许多开发人员都可能同时需要修改配置文件,但是配置文件只能同时被一个人修改,这样肯定会造成一定程度上的资源争夺,势必会影响开发效率和引起开发人员的抱怨。

在Struts 1.1中,为了解决这个并行开发的问题,提出了两种解决方案:

  1. 多个配置文件的支持
  2. 模块的支持

 

支持多个配置文件,是指你能够为ActionServlet同时指定多个xml配置文件,文件之间以逗号分隔,比如Struts提供的MailReader演示例子中就采用该种方法。


            <!-- Action Servlet Configuration -->
            <servlet>
            <servlet-name>action</servlet-name>
            <servlet-class>
                org.apache.struts.action.ActionServlet
            </servlet-class> <init-param> <param-name>config</param-name> <param-value>
/WEB-INF/struts-config.xml,
/WEB-INF/struts-config-registration.xml
</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>

这种方法可以很好地解决修改冲突的问题,不同的开发人员可以在不同的配置文件中设置自己的Action、ActionForm等等(当然不是说每个开发人员都需要自己的配置文件,可以按照系统的功能模块进行划分)。但是,这里还是存在一个潜在的问题,就是可能不同的配置文件之间会产生冲突,因为在ActionServlet初始化的时候这几个文件最终还是需要合并到一起的。比如,在struts-config.xml中配置了一个名为success的<forward>,而在struts-config-registration.xml中也配置了一个同样的<forward>,那么执行起来就会产生冲突。

为了彻底解决这种冲突,Struts 1.1中引进了模块(Module)的概念。一个模块就是一个独立的子系统,你可以在其中进行任意所需的配置,同时又不必担心和其它的配置文件产生冲突。因为前面我们讲过,ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能,需要进行以下的准备工作:

1、为每个模块准备一个配置文件

2、配置web.xml文件,通知控制器

决定采用多个模块以后,你需要将这些信息告诉控制器,这需要在web.xml文件进行配置。下面是一个典型的多模块配置:


            <init-param>
            <param-name>config</param-name>
            <param-value>
                /WEB-INF/struts-config.xml
            </param-value> </init-param> <init-param> <param-name>config/customer</param-name> <param-value>
                /WEB-INF/struts-config-customer.xml
            </param-value> </init-param> <init-param> <param-name>config/order</param-name> <param-value>
                /WEB-INF/struts-config-order.xml
            </param-value> </init-param>

要配置多个模块,你需要在原有的一个<init-param>(在Struts 1.1中将其对应的模块称为缺省模块)的基础之上,增加模块对应的<init-param>。其中<param-name>表示为config/XXX的形式,其中XXX为对应的模块名,<param-value>中还是指定模块对应的配置文件。上面这个例子说明该应用有三个模块,分别是缺省模块、customer和order,它们分别对应不同的配置文件。

3、准备各个模块所需的ActionForm、Action和JSP等资源

但是要注意的是,模块的出现也同时带来了一个问题,即如何在不同模块间进行转发?有两种方法可以实现模块间的转发,一种就是在<forward>(全局或者本地)中定义,另外一种就是利用org.apache.struts.actions.SwitchAction。

下面就是一个全局的例子:


            ...
            <struts-config>
            ...
            <global-forwards>
            <forward name="toModuleB"
            contextRelative="true"
            path="/moduleB/index.do"
            redirect="true"/>
            ...
            </global-forwards>
            ...
            </struts-config>
            

可以看出,只需要在原有的path属性前加上模块名,同时将contextRelative属性置为true即可。此外,你也可以在<action>中定义一个类似的本地<forward>。


            <action-mappings>
            <!-- Action mapping for profile form -->
            <action path="/login"
            type="com.ncu.test.LoginAction"
            name="loginForm"
            scope="request"
            input="tile.userLogin"
            validate="true">
            <forward name="success" contextRelative="true" path="/moduleA/login.do"/>
            </action>
            </action-mappings>
            

如果你已经处在其他模块,需要转回到缺省模块,那应该类似下面这样定义,即模块名为空。


            <forward name="success" contextRelative="true" path="/login.do"/>
            

此外,你也可以使用org.apache.struts.actions.SwitchAction,例如:


            ...
            <action-mappings>
            <action path="/toModule"
            type="org.apache.struts.actions.SwitchAction"/>
            ...
            </action-mappings>
            ...
            

posted @ 2007-08-17 16:25 bluoy 阅读(190) | 评论 (0)编辑 收藏

Oracle的systimestamp的精度与OS有关。例如:
select systimestamp from dual;

基于XP的输出:07-07-03 16:07:10.328000 +08:00
基于Solaris的输出:07-07-03 16:09:18.328156 +08:00


所以,如果DB中的表以timestamp类型的字段作唯一主键的话,在PC上就会藏有隐患:主键不唯一,因为精度降低了,频繁的insert操作很有可能产生相同的主键。而在Solaris上这个可能性就很低了。

这点在DB设计中还是需要加以考虑的。

posted @ 2007-07-03 16:43 bluoy 阅读(3270) | 评论 (1)编辑 收藏

java.util.Arrays.asList的BUG

jdk 1.4对java.util.Arrays.asList的定义,函数参数是Object[]。所以,在1.4中asList()并不支持基本类型的数组作参数。

jdk 1.5中,java.util.Arrays.asList的定义,函数参数是Varargs, 采用了泛型实现。同时由于autoboxing的支持,使得可以支持对象数组以及基本类型数组。

但在使用过程中发现jdk1.5中存在一个BUG。就是等参数为基本类型的数组时,函数的行为发生了变异:它不是把这个数组转换为List,而是把这个数组整体作为返回List中的第一个元素,要取得转换后的结果,得首先get(0)才行。

到网上google了一下,Sun好像认为这并不是个问题。理由如下:
Arrays.asList is now a vararg method, and the behavior is as intended:  asList(int[] ...)
The Java generics implementation does not support non-reference type parameters.
This is all standard Java 5.0 stuff.
URL:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6353471

虽然如此,但因此函数的行为就可能产生了歧义,对调用者还是会产生误导的,我认为这终归还应该是个问题的,如能解决是最好的了。

posted @ 2007-07-03 14:55 bluoy 阅读(887) | 评论 (0)编辑 收藏

问题:同事不小心把项目DB中的一个表的数据delete all了。DB版本oracle 10g。
网上简单搜了一下,搞定。以下是过程:
Oracle 10g开始,当我执行Drop Table时,Oracle也会把被删除的表放到数据库回收站(Database Recyclebin)里。这样我们就可以用flashback table命令恢复被删除的表,语法:
   Flashback table 表名 to before drop;

开始恢复,执行以下命令:
flashback table tmm2076 TO TIMESTAMP to_timestamp('2007-05-22
12:00:00','yyyy-mm-dd hh24:mi:ss')
弹出ORA-08189错误,需要执行以下命令先:
alter table tmm2076 enable row movement

这个命令的作用是,允许oracle修改分配给行的rowid。

然后再flashback,数据被恢复完毕。

posted @ 2007-05-22 16:30 bluoy 阅读(4098) | 评论 (2)编辑 收藏

There's a field introspector written by a Velocity user in the Wiki. You can configure velocity.properties to reference this. It require velocity version 1.4.

PublicFieldUberspect.java
-------------------------------------------------------------------------------------------------------------
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.velocity.tools.generic.introspection;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import org.apache.velocity.util.introspection.Info;
import org.apache.velocity.util.introspection.UberspectImpl;
import org.apache.velocity.util.introspection.VelPropertyGet;
import org.apache.velocity.util.introspection.VelPropertySet;
/**
* Uberspect implementation that exposes public fields.
* Also exposes the explicit "length" field of arrays.
*
* <p>To use, tell Velocity to use this class for introspection
* by adding the following to your velocity.properties:<br />
*
* <code>
* runtime.introspector.uberspect = org.apache.velocity.tools.generic.introspection.PublicFieldUberspect
* </code>
* </p>
*
* @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
* @version $Id: $
*/
public class PublicFieldUberspect extends UberspectImpl
{
/**
* Default constructor.
*/
public PublicFieldUberspect()
{
}
/**
* Property getter - returns VelPropertyGet appropos for #set($foo = $bar.woogie).
* <br />
* Returns a special {@link VelPropertyGet} for the <code>length</code> property of arrays.
* Otherwise tries the regular routine.  If a getter was not found,
* returns a {@link VelPropertyGet} that gets from public fields.
*
* @param obj the object
* @param identifier the name of the property
* @param i a bunch of information.
* @return a valid <code>VelPropertyGet</code>, if it was found.
* @throws Exception failed to create a valid <code>VelPropertyGet</code>.
*/
public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i)
throws Exception
{
Class clazz = obj.getClass();
boolean isArray = clazz.isArray();
boolean isLength = identifier.equals("length");
if (isArray && isLength)
{
return new ArrayLengthGetter();
}
VelPropertyGet getter = super.getPropertyGet(obj, identifier, i);
// there is no clean way to see if super succeeded
// @see http://issues.apache.org/bugzilla/show_bug.cgi?id=31742
try
{
getter.getMethodName();
return getter;
}
catch (NullPointerException notFound)
{
}
Field field = obj.getClass().getField(identifier);
if (field != null)
{
return new PublicFieldGetter(field);
}
return null;
}
/**
* Property setter - returns VelPropertySet appropos for #set($foo.bar = "geir").
* <br />
* First tries the regular routine.  If a setter was not found,
* returns a {@link VelPropertySet} that sets to public fields.
*
* @param obj the object
* @param identifier the name of the property
* @param arg the value to set to the property
* @param i a bunch of information.
* @return a valid <code>VelPropertySet</code>, if it was found.
* @throws Exception failed to create a valid <code>VelPropertySet</code>.
*/
public VelPropertySet getPropertySet(Object obj, String identifier,
Object arg, Info i) throws Exception
{
VelPropertySet setter = super.getPropertySet(obj, identifier, arg, i);
if (setter != null)
{
return setter;
}
Field field = obj.getClass().getField(identifier);
if (field != null)
{
return new PublicFieldSetter(field);
}
return null;
}
/**
* Implementation of {@link VelPropertyGet} that gets from public fields.
*
* @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
* @version $Id: $
*/
protected class PublicFieldGetter implements VelPropertyGet
{
/** The <code>Field</code> object representing the property. */
private Field field = null;
/**
* Constructor.
*
* @param field The <code>Field</code> object representing the property.
*/
public PublicFieldGetter(Field field)
{
this.field = field;
}
/**
* Returns the value of the public field.
*
* @param o the object
* @return the value
* @throws Exception failed to get the value from the object
*/
public Object invoke(Object o) throws Exception
{
return this.field.get(o);
}
/**
* This class is cacheable, so it returns <code>true</code>.
*
* @return <code>true</code>.
*/
public boolean isCacheable()
{
return true;
}
/**
* Returns <code>"public field getter"</code>, since there is no method.
*
* @return <code>"public field getter"</code>
*/
public String getMethodName()
{
return "public field getter";
}
}
/**
* Implementation of {@link VelPropertyGet} that gets length from arrays.
*
* @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
* @version $Id: $
*/
protected class ArrayLengthGetter implements VelPropertyGet
{
/**
* Constructor.
*/
public ArrayLengthGetter()
{
}
/**
* Returns the length of the array.
*
* @param o the array
* @return the length
* @throws Exception failed to get the length from the array
*/
public Object invoke(Object o) throws Exception
{
// Thanks to Eric Fixler for this refactor.
return new Integer(Array.getLength(o));
}
/**
* This class is cacheable, so it returns <code>true</code>.
*
* @return <code>true</code>.
*/
public boolean isCacheable()
{
return true;
}
/**
* Returns <code>"array length getter"</code>, since there is no method.
*
* @return <code>"array length getter"</code>
*/
public String getMethodName()
{
return "array length getter";
}
}
/**
* Implementation of {@link VelPropertySet} that sets to public fields.
*
* @author <a href="mailto:shinobu@ieee.org">Shinobu Kawai</a>
* @version $Id: $
*/
protected class PublicFieldSetter implements VelPropertySet
{
/** The <code>Field</code> object representing the property. */
private Field field = null;
/**
* Constructor.
*
* @param field The <code>Field</code> object representing the property.
*/
public PublicFieldSetter(Field field)
{
this.field = field;
}
/**
* Sets the value to the public field.
*
* @param o the object
* @param value the value to set
* @return always <code>null</code>
* @throws Exception failed to set the value to the object
*/
public Object invoke(Object o, Object value) throws Exception
{
this.field.set(o, value);
return null;
}
/**
* This class is cacheable, so it returns <code>true</code>.
*
* @return <code>true</code>.
*/
public boolean isCacheable()
{
return true;
}
/**
* Returns <code>"public field setter"</code>, since there is no method.
*
* @return <code>"public field setter"</code>
*/
public String getMethodName()
{
return "public field setter";
}
}
}


See
http://wiki.apache.org/jakarta-velocity/PublicFieldUberspect

posted @ 2007-05-18 10:10 bluoy 阅读(272) | 评论 (0)编辑 收藏