More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Java DreamsProfileFriendsBlogMore Tools Explore the Spaces community

Blog

December 22

Tapestry之Cache组件

有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容cache住,当有新的请求时,我们就response cache,这样可以减少服务器的负担,还可以提高性能。其中oscache已经可以实现页面的cache和页面部分cache。oscache使用jsp tags来实现局部cache的。拿到Tapestry中肯定是行不通的。在同事的提醒下,想到写这个Tapestry的cache组件来达到重用的目的。

 

说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。

<span jwcid="@Cache" cacheProvider="ognl:cacheProvider" updateCondition="ognl:needUpdate">

    //Cache body, which is the content you want to cache.

</span>

这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">

<component-specification allow-body="yes" allow-informal-parameters="no" class="com.live.spaces.dengyin2000.tapestry.tfancomponents.components.Cache">
   <description>
   Cache component, this component can inclue any content as its body, and cache its body.
    This is useful in rarely updated content.
    </description>
<parameter name="updateCondition" required="no" default-value="false">
    <description>
     The flag that need to refresh cache, it would casue tapestry render not use the cache.
    </description>
</parameter>
<parameter name="cacheProvider" required="yes">
     <description>
     You need to provider an cache provider to store its body content. for some simply use.
    Please see     @com.live.spaces.dengyin2000.tapestry.tfancomponents.components.SimpleHtmlSourceCacheProvider
    </description>
</parameter>
</component-specification>

下面的是ICacheProvider接口

 

public interface ICacheProvider {
/**
*
* @param cacheKey
* @param cacheContent
*/
public void storeCache(String cacheKey, String cacheContent);
/**
*
* @param cacheKey
* @return
*/
public String getCacheContent(String cacheKey);
/**
* This method provider to user, so that user can controll cache manaully.
* @param cacheKey
*/
public void removeCache(String cacheKey);
/**
* This method provider to user, so that user can controll cache manaully.
* Clear all caches
*
*/
public void reset();
}

ok。 再来看看Cache组件的代码。

 

public abstract class Cache extends AbstractComponent {
protected static final Log logger = LogFactory.getLog(Cache.class);
public abstract boolean getUpdateCondition();
public abstract ICacheProvider getCacheProvider();
@Override
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
if (getUpdateCondition()){
renderComponentWithCache(writer, cycle);
}else{
if (getCacheProvider().getCacheContent(this.getIdPath()) != null){
//response cache html content.
writer.printRaw(getCacheProvider().getCacheContent(this.getIdPath()));
}else{
renderComponentWithCache(writer, cycle);
}
}

}
private void renderComponentWithCache(IMarkupWriter writer, IRequestCycle cycle) {

logger.debug("We need to refresh cache now.");
CacheWriterWrapper cacheWrapper = new CacheWriterWrapper();
super.renderBody(buildCacheMarkupWriter(cacheWrapper.getPrintWriter(), writer), cycle);
String cacheContent = cacheWrapper.getCacheContent();
logger.debug("fetched cache content, ready to put it into cache.");

getCacheProvider().storeCache(this.getIdPath(), cacheContent);
// response html content.
writer.printRaw(cacheContent);
}
private IMarkupWriter buildCacheMarkupWriter(PrintWriter writer, IMarkupWriter sourceWriter){
return this.getPage().getRequestCycle().getInfrastructure().getMarkupWriterSource().newMarkupWriter(writer, new ContentType(sourceWriter.getContentType()));
}
class CacheWriterWrapper{
private StringWriter sw;
private PrintWriter pw;
public CacheWriterWrapper() {
sw = new StringWriter();
pw = new PrintWriter(sw);
}

public String getCacheContent(){
return sw.getBuffer().toString();
}
public PrintWriter getPrintWriter(){
return pw;
}
}
}

主要是得到cache组件body的内容,然后把body的内容cache住,下次的话就response Cache的内容。 其实也是满简单的。

我自己还写了一个简单CacheProvider。

 

public class SimpleHtmlSourceCacheProvider implements ICacheProvider {
private Map<String, String> cache = new HashMap<String, String>();
public String getCacheContent(String cacheKey) {
return cache.get(cacheKey);
}

public void storeCache(String cacheKey, String cacheContent) {
cache.put(cacheKey, cacheContent);
}

public void removeCache(String cacheKey) {
cache.remove(cacheKey);
}

public void reset() {
cache.clear();
}
}

在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。

我在google code host上面建了一个probject地址是http://code.google.com/p/tfancomponents/ 有兴趣的同学可以看看, 这是一个maven项目。

November 29

提高eclipse在windows下的性能

在windows中,假如程序处理一定的状态下,会把memory放到paging里面。这样就降低了性能,但提高了memory的利用率。

打开windows注册表, 找到 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\DisablePagingExecutive  值, 然后把这个值1。 这样应用程序就会一直使用物理内存了。

详细请看:http://technet2.microsoft.com/WindowsServer/en/library/3d3b3c16-c901-46de-8485-166a819af3ad1033.mspx?mfr=true
November 24

让GWT的FlexTable支持双击(double click)

Each event has a set of browser events that fires it.  For example take

a look at the source of the HTMLTable Class in the gwt-user jar.  It
has the following constructor:

  public HTMLTable() {
    tableElem = DOM.createTable();
    bodyElem = DOM.createTBody();
    DOM.appendChild(tableElem, bodyElem);
    setElement(tableElem);
    sinkEvents(Event.ONCLICK);
  }

Basically, it is "sinking" only the ONCLICK event, and will ignore all
other events.   To 'sink' and event just means to react to any firings
of that event.  A full list of the various events are listed here:

http://code.google.com/webtoolkit/documentation/com.google.gwt.user.c...

So, for example, if you wanted the table to respond to ONDBLCLICK
events, all you need to do is extend the class of the table you want to

use (let's say FlexTable), so you would make the class:

public class HappyTable extends FlexTable {
        public HappyTable(){
                super();
                addTableListener(this);
                sinkEvents(Event.ONCLICK | Event.ONDBLCLICK |
Event.ONKEYDOWN);
        }
...

}

What this code is doing, is telling the table to react to click, double

click, and key press events.  In the same code you would create an
onBrowser event method which would define what you want to do:

public void onBrowserEvent(Event event) {
                // Find out which cell was actually clicked.
                Element td = getEventTargetCell(event);
                if (td == null) {
                        return;
                }
                Element tr = DOM.getParent(td);
                Element body = DOM.getParent(tr);
                int row = DOM.getChildIndex(body, tr);
                int column = DOM.getChildIndex(tr, td);
                switch (DOM.eventGetType(event)) {
                case Event.ONCLICK: {
                        if (this.tableListeners != null) {
                                // Fire the event.
                                tableListeners.fireCellClicked(this,
row, column);
                        }
                        break;

                }
                case Event.ONDBLCLICK: {
                        if (this.tableListeners != null) {
                                // Fire the event.
                                tableListeners.fireCellDblClicked(this,
row, column);
                        }
                        break;
                }
                case Event.ONKEYDOWN: {
                        if (DOM.eventGetKeyCode(event) == KEY_UP) {
                                // Fire the event.
                                tableListeners.fireUpKey(this);
                        }
                        else if (DOM.eventGetKeyCode(event) ==
KEY_DOWN) {
                                // Fire the event.
                                tableListeners.fireDownKey(this);
                        }
                        break;
                }
                default: {
                        // Do nothing
                }

                }
        }

Because I was doing a variety of things with the table I created my own

listener interface, and listener collection which included double
clicks, but this is not necessary for simpler things.  Here it is
anyway (note that this implements all of clicks, dblclicks, and up/down

keys):

public interface HappyTableListener extends TableListener{

        public void onCellDblClicked(SourcesTableEvents sender, int
row, int
cell);
        public void onUpKey(SourcesTableEvents sender);
        public void onDownKey(SourcesTableEvents sender);

}

public class MyTableListenerCollection extends Vector {

        public void fireCellClicked(SourcesTableEvents sender, int row,
int
cell) {
                for (Iterator it = iterator(); it.hasNext();) {
                        MyTableListener listener = (MyTableListener)
it.next();
                        listener.onCellClicked(sender, row, cell);
                }
        }

        public void fireCellDblClicked(SourcesTableEvents sender, int
row, int
cell) {
                for (Iterator it = iterator(); it.hasNext();) {
                        MyTableListener listener = (MyTableListener)
it.next();
                        listener.onCellDblClicked(sender, row, cell);
                }
        }

        public void fireUpKey(SourcesTableEvents sender) {
                for (Iterator it = iterator(); it.hasNext();) {
                        MyTableListener listener = (MyTableListener)
it.next();
                        listener.onUpKey(sender);
                }
        }
        public void fireDownKey(SourcesTableEvents sender) {
                for (Iterator it = iterator(); it.hasNext();) {
                        MyTableListener listener = (MyTableListener)
it.next();
                        listener.onDownKey(sender);
                }
        }

详细请看:http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/861b1cb22c8423c3/fcaf84884d8d3d13?lnk=gst&q=table+row+double+click&rnum=1#fcaf84884d8d3d13

November 15

Dojo TreeV3使用详解

Dojo TreeV3使用详解

                                              作者:邓胤(deng.yin@gmail.com)

    工作中使用了TreeV3这个dojo的组件,感觉基本上已经是把dojo的treeV3使用到了极点(自定义树的外观,树节点的拖拉,把其他Drag Source拖拉到树中),公司也要求我作个treeV3演说。所以特意把这篇文章写下来。

    首先先对treeV3做一个简单的介绍。TreeV3.js, TreeNodeV3.js, .TreeBasicControllerV3.js, TreeContextMenuV3.js,TreeDndControllerV3.js,TreeEditor.js, 主要的就是这些js一起协作。有兴趣的可以看看源码, 其实dojo的代码看起来还算是瞒简单的。下面我就用几个例子来说明怎样扩展或自定义TreeV3。本篇文章是增对有一定dojo知识的读者,如果你现在还不了解dojo,请看
http://dojotoolkit.org/.

    1.  为叶子节点增加图标。
       IconTree.html
      
<div dojoType="TreeV3" listeners="controller">
    <div dojoType="TreeNodeV3" title="Item 1" widgetId="1">
        <div dojoType="TreeNodeV3" childIconSrc="images/page.gif" title="Item 1.1" widgetId="Item 1.1"></div>
        <div dojoType="TreeNodeV3" childIconSrc="images/page.gif" title="Item 1.2" widgetId="Item 1.2"></div>
    </div>

    <div dojoType="TreeNodeV3" title="Item 2" widgetId="Item 2">
        <div dojoType="TreeNodeV3" childIconSrc="images/page.gif" title="Item 2.1" widgetId="Item 2.1"></div>
    </div>

    <div dojoType="TreeNodeV3" title="Empty Folder" isFolder="true" widgetId="Item 3"></div>
    <div dojoType="TreeNodeV3" childIconSrc="images/page.gif" title="Item 4" widgetId="Item 4"></div>
</div>
    我们在每个TreeNode上加上childIconSrc属性。请看icontree.js怎样让这个属性生效的。
    icontree.js
dojo.lang.extend(dojo.widget.TreeNodeV3, {
    childIconsrc: "",
    childIcon: null,
    iconNode:null,
    titleNode:null,
    postCreate: function(args) {
    //build icon
        if (args["childIconsrc"]) {
            this.childIconsrc = args["childIconsrc"];
        }
        this.childIcon = document.createElement("img");
        if (this.childIconsrc != "") {
            this.childIcon.src = this.childIconsrc;
            this.childIcon.setAttribute("width", "16");
            this.childIcon.setAttribute("height", "16");
        }
        this.iconNode = this.tree.labelNodeTemplate.cloneNode(true);
        this.titleNode = this.tree.labelNodeTemplate.cloneNode(true);
        if (!this.isFolder){
            //clear treenode, if it is not folder node
            this.labelNode.innerHTML="";
        }
        this.titleNode.innerHTML=this.title;
        this.iconNode.appendChild(this.childIcon);
        // add icon first, then add title
        this.labelNode.appendChild(this.iconNode);
        this.labelNode.appendChild(this.titleNode);       
    }
});
我们扩展了TreeNodeV3这个组件的postCreate方法(dojo组件都有这个方法,他相当于构造方法吧,我们可以在这里做必要的初始化),这里做的事应该比较清楚,我们通过childIconsrc这个属性创建了iconNode, 然后清空TreeNodeV3的labelNode。再增加iconNode和titleNode

2. 拖动物体到tree中
dragother.html
<div dojoType="TreeV3" DndMode="between;onto" DndAcceptTypes="firstTree;feed" widgetId="firstTree" listeners="basicController;dndcontroller;selector;disableWrap" toggle="fade" showGrid="false" showRootGrid="true">
    <div dojoType="TreeNodeV3" title="Item 1" widgetId="1">
        <div dojoType="TreeNodeV3"  title="Item 1.1" widgetId="Item 1.1"></div>
        <div dojoType="TreeNodeV3" title="Item 1.2" widgetId="Item 1.2"></div>
    </div>

    <div dojoType="TreeNodeV3" title="Item 2" widgetId="Item 2">
        <div dojoType="TreeNodeV3" title="Item 2.1" widgetId="Item 2.1"></div>
    </div>

    <div dojoType="TreeNodeV3" title="Empty Folder" isFolder="true" widgetId="Item 3"></div>
    <div dojoType="TreeNodeV3" title="Item 4" widgetId="Item 4"></div>
</div>

<br/>

<span id="feed_0">Drag me0 to tree.</span><br/>
<span id="feed_1">Drag me1 to tree.</span><br/>
<span id="feed_2">Drag me2 to tree.</span><br/>
<span>You can't drag me.</span>
注意黑体的DndAcceptTypes属性。说明这个树接受dragSource type为firstTree或者feed的(也就是自己,还有就是下面的span, 我们需要把span变成可以拖动的物体 dragSource)。再看dragother.js。
    dojo.addOnLoad(function(){
           var num = 0;
           while(dojo.byId("feed_" + num) != null){
               var dropSource = new dojo.dnd.HtmlDragSource(dojo.byId("feed_" + num), "feed");
               num++;
        }   
    });

dojo.dnd.TreeDropTargetV3.prototype.oldGetDropHandler = dojo.dnd.TreeDropTargetV3.prototype.getDropHandler;
dojo.lang.extend(dojo.dnd.TreeDropTargetV3, {
   
    getDropHandler: function(e, source, targetParent, targetIndex) {
        if (source.type == "feed"){
            var sourceNode = source.domNode;
            if (dojo.widget.byId(sourceNode.id) != null){
                alert("this widget has already been here.");
                return function(){
                    return false;
                }
            }            
            var node = createTreeNode(sourceNode.id, sourceNode.innerHTML);
            targetParent.addChild(node, targetIndex);
            return function(){
                return true;
            }
        }
        return this.oldGetDropHandler(e, source, targetParent, targetIndex);
    }   
});   

function createTreeNode(widgetId, title) {
    return dojo.widget.createWidget("TreeNodeV3",
    {
        widgetId: widgetId,                                                   
        title: title,
        isFolder: false,
        tree: 'firstTree'
    });
}

第一段是让那些span成为dragsource。第二段我们hack了dojo.dnd.TreeDropTargetV3的 getDropHandler方法(具体可以看看TreeDndControllerV3.js)。当我们接收到dragSources时我们获取那些 span中的一些信息,然后create 一个treeNode,在把这个treeNode加到树中。

3.   ...................................................
4.   ...................................................
5.   ...................................................

还有一些hack treeV3的东西实在不愿写。 dojo的treeV3真的是蛮强大的(仔细看看那几个**Controller和TreeV3 TreeNodeV3的源码), 而且dojo的widget源码还是蛮容易理解的。有兴趣的朋友可以看看dojo的源码。还有就是dojo包里面tests目录下面的例子。大多数应用的话看看里面的例子也就行了。

例 子的源码可以在http://deng.yin.googlepages.com/TreeV3Sample.zip下载。本例子中没有包括 dojo0.4源码,用户可以到http://download.dojotoolkit.org/release-0.4.0/dojo-0.4.0- ajax.zip下载源码, 然后解压到例子中的dojo目录。

格式不好的话可以看http://docs.google.com/View?docid=ajgd3tgv958v_3gz374h

HttpURLConnection 访问页面时发生403问题。

工作中发现一个问题。当我用HttpURLConnection去连接读取一个网站时,老是会发生这个403错误。这个引起了IOException,但是我用firefox访问这个网站时就没问题。 google后知道了答案。原来如果用java代码HttpURLConnection去连的话 http header 中的User-Agent就为空,解决方法就是在连接之前先设置这个属性。
URL myUrl = new URL(searchURL);
URLConnection myConn = (HttpURLConnection)myUrl.openConnection();
myConn.setRequestProperty("User-agent","Mozilla/4.0");
BufferedReader br = new BufferedReader(new InputStreamReader(myConn.getInputStream()));

那台Server上要这么做, 可能是要组织一些网络机器人的访问(不过感觉不是很有用,用上面的方法就能破了)。 其实实现感觉也很简单, 加上一个Filter,判断如果request.getHeader("User-agent")为空的话,然后再response一个403 status就行。

November 07

晕,inputstream for get image from internet.

需要网站的favicon保存到数据库中。思路很简单连接internet,然后得到图片的bytes保存到数据库的blob字段就行。但是我却在取到图片的bytes上面浪费了许多时间。

开始的代码如下
    boolean fetched = false;
        URL url = null;
        try {
            url = new URL("http://" + channel.getSite().getHost() + "/favicon.ico");
            HttpURLConnection httpURL = (HttpURLConnection) url.openConnection();
            //httpURL.setConnectTimeout(60*1000);
            httpURL.connect();
            if (httpURL.getResponseCode()==200){
                InputStream is = httpURL.getInputStream();
                int length = is.available();
                byte[] bytes = new byte[length];
                is.read(bytes, 0, length);
                Blob blob = Hibernate.createBlob(bytes);
                ((Image)image).setLocalSmallImage(blob);
                logger.debug("Image URL:[" + url + "] has been fetched.");
                logger.debug("read image size:" + length);
                fetched = true;
            }
        } catch (Exception e)    {
            //ignored
        }
        if (!fetched)
            logger.debug("Fail to fetch Image URL:[" + url + "] ");
在本地上设置断点调试发现一切正常。 但是发不到服务器上却发现数据更本没有保存到进去,或者只保存进去一部分。奇怪!然后log了bytes的长度(logger.debug("read image size:" + length);)。发现这时候的长度为0。上面的代码肯定是有问题。 因为网络延时之类的这里的available根本就不准确。其实这里我们应该像读取一个文件,然后在把他写入另一个文件的操作是一样的。需要先用过inputstream read出bytes, 然后再通过outputstream把bytes输出。 但是这里我们不需要写到文件之类的datasource中。我们需要的只是bytes。我们可以方便的使用ByteArrayOutputStream来存储我们的bytes。

    public static byte[] getAllBytes(InputStream in) throws Exception {
        int chunkSize = 4096;
        byte[] b = new byte[chunkSize];
        int borb = -1;
        ByteArrayOutputStream fos = new ByteArrayOutputStream();
        while ((borb = in.read(b)) != -1) {
                fos.write(b, 0, borb);
        }
        return fos.toByteArray();
    }

升级到Edgy后, Vmware server不能启动。

I can't start vmware server after I upgrade Ubuntu to lastest version "Edgy". do as this article(http://dengyin2000.spaces.live.com/blog/cns!AF4AB52B167D7EE7!237.entry), it still can't work. Finally I google an solution for this problem, please see http://www.debian-administration.org/users/emeitner/weblog/6

change command "vmware" to "LD_PRELOAD=/usr/lib/libdbus-1.so.3:$LD_PRELOAD vmware"


October 25

小试GWT

当gwt发布的时候我就初略的看了gwt的文档。当时没有在注意这个东西。当自己经过ajax, javascript洗礼后,蓦然想试试gwt这个东西。原卷了javascript的开发效率(虽然FF 有firebug, IE下面有VS)。我也不确定gwt是否会提高开发效率(我也没有用gwt做过项目),但是就评google的技术,而且可以用java去写页面代码。 我觉得有必要试试。

发了些时间看了gwt的Getting started guideDevelop guide  这个写得还是非常简单明了的。gwt会把你写的这些client java代码编译成html和js。应该大部分都是js吧。

在实践Reomte produce call 遇到的一个问题, 我把 MyService.java MyServiceImpl.java, MyServiceAsync.java都放在了com.dengyin.client包中,然后程序运行的时候老是会出现"com.google.gwt.user.server包找不到的错误", 但是程序运行是正常的。但是classpath中确实有MyServiceImpl这个类,后来在gwt develop forum    找到答案。 问题原因应该是gwt在真正运行前会先独立的编译com.dengyin.client包下的所有的类。但在编译的时候是不会把com.google.gwt.user.server中的类include进来。但是MyServiceImpl继承了RemoteServiceServlet,RemoteServiceServlet是在com.google.gwt.user.server包里面的,所以会发生这个问题。其实想想也就知道gwt为什么强制用户要有client这个包的原因了, 所有在client包里面的类都不应该跟Server端的有关系,在这个包里面的所有类应该仅仅是跟界面有关系。解决办法是把MyServiceImpl移到com.dengyin.server包里面。
October 20

巧妙使用javascript让你的页面程序处于index frame中。

假如我们有这个一个页面,  index.html
<frameset framespacing="0" border="false" cols="180,*" frameborder="1">
<frame name="left"  scrolling="auto" marginwidth="0" marginheight="0" src="Toc.html">
<frame name="main" scrolling="auto" src="Content.html">
  </frameset>
  <noframes>
  <body>
  <p>This page uses frames, but your browser doesn't support them.</p>
  </body>
  </noframes>

Toc.html是目录页面, Content.html是内容页面。     

场景1:假如一个用户登入后, 进入index.html,然后用户过了很长一段时间没有操作session timeout了。这时候用户再去点页面的操作的话,这时候Content.html会转到登入页面, 但是因为在一个frame里面, 所以登入页面会在index.html中。我们希望他不出现在index.html中, 清在登入页面加上下面这段javascript
<script type="text/javascript">
    if (window.top != self){
        window.top.location = self.location;
    }
</script>

场景2:我们希望右边的内容页面不能独立的出现(即一定要出现在index.html中),我们也需要在每个在“main” frame的页面加上下面这段javascript
if (window.top == self){
    // ensure sub page would contain in index page
    window.location="index.html";
}
October 10

使用Maven和WTP开发WEB项目。

首先下载、安装Maven WTP。

Maven: http://maven.apache.org/download.html
WTP:
www.eclipse.org/webtools/ 建议使用1.03 或 1.5.1

首先你用Maven创建一个WEB项目,其实就是在你的pom.xml指定<packaging>war</packaging>就行了。然后自己在 src/main目录下面建立webapp web.xml等web项目需要的文件。 ok。 不知道的话请参阅Maven文档。

假设你的web项目已经用maven搭建好了。然后运行mvn clean install -Dtest , maven会自动从网上download依赖的包, 编译源码然后把声称的war放到你的资源库中。其中-Dtest是在打包之前跳过单元测试。

再运行mvn eclipse:eclipse -Dwtpversion=1.0 -DdownloadSources=true,maven会使用他的eclipse插件(如果没有的话,maven会自动download install这个插件)为你把这个项目转成eclipse的wtp项目。-Dwtpversion=1.0这里是指定wtp的版本,当前好像支持R7和1.0,但是因为1.5版本的wtp配置文件没有更改,所以-Dwtpversion=1.0一样适合1.5的版本。

配置wtp,添加你刚才那个项目到wtp Server中。 启动Server。这里有个好处就是他不会把dependency lib的scope为test 或 provided的lib考到webapp下。

当你更改了pom.xml后, 你还需要再运行下mvn eclipse:eclipse -Dwtpversion=1.0来更新你的wtp的配置文件。

我在使用wtp中发现一个非常严重的性能问题。 当你publish的文件非常多的时候,你保存一个文件时的性能非常低,有时候会需要6-10秒。wtp把你项目中需要deploy的文件都保存一个像这样的一个file:///home/denny/workspace/.metadata/.plugins/org.eclipse.wst.server.core/publish/publish1.xml文件中。假如你保存的那个文件位于publish.xml中比较靠头,那还是非常快的。 如果比较靠后就非常慢了。应为wtp需要更新你保存文件对应的stamp属性。假如非常考后的话,他需要先装在publish.xml文件, 然后找到你保存的文件再更新他的stamp属性。。

October 09

How can I move text cursor in a text input field?

Thanks the following codes. while in Firefox, you just need to invoke textElement.focus() method.

So here is how to position the caret end the end of a text field/text
area with IE4/5:

<SCRIPT>
function setCaretToEnd (el) {
if (el.createTextRange) {
var v = el.value;
var r = el.createTextRange();
r.moveStart('character', v.length);
r.select();
}
}
function insertAtEnd (el, txt) {
el.value += txt;
setCaretToEnd (el);
}
</SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="text" NAME="aText" SIZE="40">
<BR>
<INPUT TYPE="text" NAME="a2ndText" VALUE="Kibology for all.">
<INPUT TYPE="button" VALUE="insert and move to end"
ONCLICK="insertAtEnd (this.form.aText,
this.form.a2ndText.value);"
>
<BR>
<INPUT TYPE="text" NAME="a3rdText" VALUE="All for Kibology.">
<INPUT TYPE="button" VALUE="insert and move to end"
ONCLICK="insertAtEnd (this.form.aTextArea,
this.form.a3rdText.value);"
>
<BR>
<TEXTAREA NAME="aTextArea" ROWS="5" COLS="20" WRAP="soft"></TEXTAREA>
</FORM>


http://www.faqts.com/knowledge_base/view.phtml/aid/17749/fid/53
October 04

国庆购机柯达C603

国庆在国美买了柯达C603, 总体感觉还不错。。 1399 + 512SD卡 + 手提袋 + 充电器和两只充电电池


* 610万像素
* 3倍光学变焦
* 4倍数码变焦
* 2.4寸显示屏(11.2万像素)
* 17种场景拍摄模式
* 内置28M内存

September 19

安装VMWare Server, 模拟Windows Xp

虽说以前通过linux4ie安装了IE, 但这个确实不好用, 一旦有javascript错误,看不到javascript错误弹出窗口,对调式来说的话根本就没有, 所以其实跟没有一样,所以调式IE的话,我还是希望切换到windows xp中用VS调式javascript。今天狠下心装了VMWare Server, 再在上面装了一个Window XP。 虽说慢一点(鼠标有点晃),其实的跟真正的Windows没有区别。

安装VMWare Server  
http://forum.ubuntu.org.cn/viewtopic.php?t=22441
http://thinkbase.net/w/main/Wiki?2006-08-26+%E5%9C%A8+Ubuntu+6.06+%E4%B8%8A%E5%AE%89%E8%A3%85+VMware-server+1.0.1

今天发现一个问题, 我更新内核后发现VMWare需要重新设置。 我们只学要再运行下
这个应该内核的C库吧。
sudo apt-get install linux-headers-`uname -r` build-essential xinetd
然后再重新配置下
sudo /usr/bin/vmware-config.pl

Show 下我在Ubuntu下的Windows XP

September 17

File permission (chmod)

Options

Definition

u

owner

g

group

o

other

x

execute

w

write

r

read

+

add permission

-

remove permission

=

set permission


user@host:/home/user$ touch file1 file2 file3 file4
user@host:/home/user$ ls -l
total 0
-rw-r--r-- 1 user user 0 Nov 19 20:13 file1
-rw-r--r-- 1 user user 0 Nov 19 20:13 file2
-rw-r--r-- 1 user user 0 Nov 19 20:13 file3
-rw-r--r-- 1 user user 0 Nov 19 20:13 file4

Add owner execute bit:

user@host:/home/user$ chmod u+x file1
user@host:/home/user$ ls -l file1
-rwxr--r-- 1 user user 0 Nov 19 20:13 file1

Add other write & execute bit:

user@host:/home/user$ chmod o+wx file2
user@host:/home/user$ ls -l file2
-rw-r--rwx 1 user user 0 Nov 19 20:13 file2

Remove group read bit:

user@host:/home/user$ chmod g-r file3
user@host:/home/user$ ls -l file3
-rw----r-- 1 user user 0 Nov 19 20:13 file3

Add read, write and execute to everyone:

user@host:/home/user$ chmod ugo+rwx file4
user@host:/home/user$ ls -l file4
-rwxrwxrwx 1 user user 0 Nov 19 20:13 file4
user@host:/home/user$

Details in: https://help.ubuntu.com/community/FilePermissions
September 15

Install xubuntu-desktop

今天装了xubuntu了,耗资源少点,试了下还真不错。show张图片
September 14

Add font in Ubuntu

下载字体(通常是以ttf格式的), copy到`/.fonts目录下。  然后运行sudo fc-cache -f -v来更新font库。
September 12

Hack dojo codes with dojo's util

dojo.lang.extend(dojo.widget.PopupMenu2, {
    onOpen: function(e){
        this.openEvent = e;
        var x = e.pageX, y = e.pageY;

        var win = dojo.html.getElementWindow(e.target);
        var iframe = win._frameElement || win.frameElement;
        if(iframe){
            var cood = dojo.html.abs(iframe, true);
            x += cood.x - dojo.withGlobal(win, dojo.html.getScroll).left;
            //override the onOpen to reslove the problem the context popup menu open under the selected TreeNode.
            if (!(e.type == "contextmenu" && dojo.render.html.ie))
                y += cood.y - dojo.withGlobal(win, dojo.html.getScroll).top;
        }
        this.open(x, y, null, [x, y]);

        e.preventDefault();
        e.stopPropagation();
    }
});

这样我们就是复写了dojo.widget.PopupMenu2类的onOpen方法。如果我们想调用覆盖以前的方法。
//backup the old function
dojo.widget.TreeBasicControllerV3.prototype.oldOnKey =dojo.widget.TreeBasicControllerV3.prototype.onKey;
dojo.lang.extend(dojo.widget.TreeBasicControllerV3, {
    onClick: function(e) {
        if (e.target.tagName == "INPUT")
            return ;
        // default click handler just sets the focus
        var treeWidget = this.getWidgetByNode(e.currentTarget);
        if (!treeWidget || !treeWidget.isTree) { return; }
        var nodeWidget = this.getWidgetByNode(e.target);
        if (!nodeWidget || !nodeWidget.isTreeNode) { return; }
        this._focusLabel(treeWidget, nodeWidget);
    },
    onKey: function (e){
        if (e.target.tagName == "INPUT")
            return ;
        this.oldOnKey(e);
    }
});

dojo.lang.extend这个方式是多么的方便。我们可以用这个方法方便的扩展或修改以有的代码。

看看dojo的dojo.lang.common  里面包括了对象间的一些操作。如dojo.lang.inherits, dojo.lang.mixin etc
September 06

Ubuntu 常用技巧

快速设置指南
http://wiki.ubuntu.org.cn/%E5%BF%AB%E9%80%9F%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%8D%97/DapperDrake

挂载硬盘
/etc/fstab

/dev/hda1      /windows/C      ntfs    auto,user,ro,nls=utf8,umask
=000   0   0
/dev/hda5      /windows/D      vfat    auto,user,rw,utf8,umask=000   0   0
/dev/hda6      /windows/E      vfat    auto,user,rw,utf8,umask=000  0   0

http://forum.ubuntu.org.cn/about19112.html


环境变量的设置

/home/denny/.bashrc

export JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun-1.5.0.06
export CLASSPATH=$CLASSPATH:$JAVA
_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export MAVEN_HOME=/usr/local/maven-2.0.4
export PATH=$PATH:$MAVEN_HOME/bin:$JAVA_HOME/jre/bin:$JAVA_HOME/bin:.

adsl拨号设置

第一次使用 sudo pppoeconf 设置好了之后以后只要使用下面两个命令拨号或断线。

sudo pon dsl-provider
sudo poff

设置xserver 主要有显示器分辨率等等
sudo dpkg-reconfigure xserver-x

安装MPlayer
http://wiki.ubuntu.org.cn/%E5%AE%89%E8%A3%85MPlayer



javascript中的继承。

本来打算写篇关于javascript继承的文章, 但是觉得这篇文章已经写得够好了。

http://forum.javaeye.com/viewtopic.php?t=19748