Friday, August 20, 2010

Working style

There are 20+ staffs in Salzburg office. Most of them are developers, one is administrator of office.
Generally the staffs in Salzburg work more flexible than the staffs working in Beijing.
Some of them live in German. Even though it's not so far as Salzburg, they also need come to Salzburg by train. So sometimes they work at home, use internet and phone as communication tool.
And they have different responsibilities for products. For example, Helmut works on installer, Matthias and Michael are responsibility for QFT testing, Martin N. is focus on license API developing. So everybody has himself schedule, he can decide when he come to office and when leave office based on his working schedule. Nobody cares when you come/leave office or how long you work every day. I believe all of them do well on their jobs.
Furthermore you can work with your dogs together if nobody takes care of them at home.
Max's dogs
Most of foreign like coffee, so there is a kitchen with seats in the office. Some of them like to drink a cup of coffee or tea as a break, and it's a good chance to talk with others. It's a relaxing time for changing your mind out of work. Besides drinking some things, there is a room for playing table football game. It's a small amount of exercise, it's good for body.

Another thing makes me very impressive is that the team is very stable than any company I know in China. Most of them work in company more than 10 years. So I think I know that's why they know more than us. Everyone could be expert after doing the same thing more than 10 years. They love the work of coding, and they would like to do coding until retiring. That's why I can see some of them are more than 40, even 50 years old.

Tuesday, August 10, 2010

day 1


度过长途飞行的旅程不是一件容易的事。要在狭小的空间里待上近10个小时,好在是两人出行,半睡半聊的打发过了时间。
到达维也纳之后,出了登机通道看到的居然是一个酒吧类的餐馆。感觉很稀奇,也很有味道。
周围当然少不了免税店和商铺,但远没有首都机场那样的规模。总体感觉就像国内大型超市购物出口一样,而且人也不多。

另外赞一下维也纳机场的Wifi,简单配置就K了,哪像国内的,又要移动号码,还要短信获取,搞半天也没弄定。
转机之前还有段时间,就在机场里到处逛了逛。顺便在一个吧解决了晚餐,同时也尝了杯当地啤酒。

去萨尔茨堡的飞机还是带螺旋桨的,头次坐这样的老式飞机。

Monday, May 17, 2010

Discovering the p2 API

Check out this SlideShare Presentation:

P2 replication tool lives on Eclipse Marketplace

Days ago I updated my p2 replication tool. It's easier to install it in your Eclipse.
A new component named 'Eclipse marketplace' is added into Eclipse SDK since Helios, which is an application store for Eclipse. People could be easy to install third party plug-ins into their Eclipse.

You can launch marketplace via 'Help' - 'Eclipse Marketplace...', then search key word 'p2' or 'replication' to find the tool. Finally click next to install it.

It's a very graceful workflow to install some add-ons like firefox.

And then p2 replication tool could help you replicate your environment. This tool supports install components from another existing Eclipse instance to save the time cost on downloading them from Internet now! Enjoy it.

Thursday, March 11, 2010

useful network utility tools

1. tcpdump
tcpdump -n port 80 -i eth0|lo
monitor all package transferred on 80 port on the network interface eth0/lo
2. netstat
netstat -anp|grep java
trace all network traffic on the process named java
netstat -anp|grep 128.224.159.xxx
trace all network traffic on the host whose ip address is 128.224.159.xxx
3. nslookup
nslookup 206.191.52.46
look up the domain name whose ip address is 206.191.52.46

Wednesday, February 24, 2010

[tip]Find -exec tip

Using -exec command like below, need add escape character for semicolon that separated two commands in shell

find directory/ -type d -exec chmod a+x {} \;

Feb 24, 2010 - update:
find . -maxdepth 4 -type d  -name 'g-vxworks' 2>/dev/null -print

Friday, February 5, 2010

special characters in p2 touchpoint instruction

I suffered p2 installation failed on the configure parse. Becase I try to add vm arguments for my application.
For example, I added '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8272' in the product configuration.
P2 will fail when parsing the argument, because it contains ':' and ',' that should be escaped.
It works again after replacing it to '-agentlib${#58}jdwp=transport=dt_socket${#44}server=y${#44}suspend=n${#44}address=8272'.
The more detail note could be found in p2 touchpoint wiki.
And I also opened bug to request improving it.

Friday, January 29, 2010

mount windows share folder

mount -t cifs -o username=xxx,password=xxx,workgroup=xx,iocharset=utf8 //share.domain/folder /localfolder

Wednesday, January 27, 2010

Monday, January 11, 2010

How to get the name of running test case in JUnit4

public class NameRuleTest {
   
@Rule public TestName name = new TestName();

       
@Test public void testA() {
                assertEquals
("testA", name.getMethodName());
       
}

       
@Test public void testB() {
                assertEquals
("testB", name.getMethodName());
       
}
}

Wednesday, December 30, 2009

How p2 UI handles with license agreements

P2 install wizard firstly query the repository to find out the root installable unit(as well as top installable). Then p2 recalculate the dependency and try to search the requirements in all available repositories after user submits their installation request. Go to the license agreement page if all the dependencies are satisfied.

P2 agreement page obtains all the units to be installed from the operands of provision plan. The number always is much greater than the number submitted by user. Because the submitted IUs only are the root IUs.

P2 UI would check the unaccepted licenses comparing to before records. The policy class of p2 UI provides the license manager to record the even accepted license. It traverses all the installable units, querying its license whether it has already been accepted if it has. If the license agreement has been accepted, it would be ignored, won't be shown in the agreement page. Otherwise, new record is created to mark it as accepted by the license manager and display it in the agreement wizard page.

The default implementation of license manager would persist the accepted information in the file -- <workspace>/.metadata/.plugins/org.eclipse.equinox.p2.ui.sdk/license.xml.

Tuesday, December 29, 2009

[tip]ssh key

Setup SSH without password.
a) execute "ssh-keygen -t rsa" under your linux/unix login to get the RSA keys.
(press Enter for all)
You will get 2 files uner ~/.ssh/, id_rsa and id_rsa.pub
b) Put the public key id_rsa.pub to your remote host: ~/.ssh/authorized_keys If the remote host share the same nfs, just try " cat id_rsa.pub >> ~/.ssh/authorized_keys"
* Remember to modify hostname or ip info in ~/.ssh/authorized_keys to "*", so that you can login from any host without password in your NIS domain.
For example:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA4Ri5J0s1BL/+mR7RfAuDW6FY2P6ILc61Zvw1BdDkvHMFrTzaC/AUMw33H7biAMCXuCleakCuSoV8ZDiGHYs4wOVvet5sDmphkwdiC4xTekdl3dRNvGjMVbvFUta/Y5CiayL6YIu47Ro6Vvu4Mutsrv/13pTlifrEz+NTR/+bzMb9nTniCwiryMyYod3E46b8WvS8yE3WK+tH4BZE8bjiCwdvAzSdPyk/OFNrlBNuF1yewwnxv1roRD3UalT2+7O4kfEG9sMvvBHjuX2l7xlUe3stBftYpigBbwGmmadxjRpNIlk88t5xKcQX6nSu7V8HI3GWPHI0D+ISIlbfU5Sunw== kzhu0@*

Friday, December 25, 2009

[Eclipse][P2]P2 replication plug-in

I wrote a plug-in to simplify the process to install the same plug-ins in different platform or different workstation.
Anyone is interested in it, pls follow below guide to freely use it.
http://code.google.com/p/kane-toolkit/wiki/P2Replication

Enjoy it.

Wednesday, December 2, 2009

[eclipse]How Equinox load bundles

How Equinox load bundles


Equinox launcher is responsible to start OSGi framework. The system bundle would be created and marked as installed when initializing the framework. Equinox also tries to install the installed bundles if finding them in persistence data during the initializing period. Of course there is no extra bundles would be installed when launching Equinox first time.


Then Equinox launcher would install the bundles specified by vm's system property 'osgi.bundles'. And start the initial bundles that are marked as early start. For example, let's have a look at the configuration/config.ini of Eclipse, you would find a line similar as below,
osgi.bundles=reference\:file\:org.eclipse.equinox.simpleconfigurator_1.0.200.v20090831.jar@1\:start
It means the start level of bundle 'org.eclipse.equinox.simpleconfigurator_1.0.200.v20090831.jar' is 1, and it would be started after installing it.

Here you would ask there are only two bundles are installed(one is system bundle 'org.eclipse.osgi', the other is 'org.eclipse.equinox.simpleconfigurator') when launching Equinox, how the other bundles are installed? It's done by the activate method of 'simpleconfigurator' bundle. The available bundles are recorded in plain text file configuration/org.eclipse.equinox.simpleconfigurator/bundles.info, simpleconfigurator read the file then install those bundles.

It's a new bundle management introduced by p2. P2 also supports the traditional way to install extensions, such as link file, .eclipseproduct file and directly copying features/plugins.
Below table lists the p2 bundles to implement the
compatibility installation feature,


Bundle
Usage
org.eclipse.equinox.p2.directorywatcher
the definition and implementation of directory watcher API
org.eclipse.equinox.p2.updatesite
the implementation of updatesite repository
org.eclipse.equinox.p2.extensionlocation
the implementation of extension repository
org.eclipse.equinox.p2.reconciler.dropins
scan dropin folder and link files; watch the traditional configuration file used by update manager

P2 reconciler would scan the dropin, link folder and legacy configuration file in every Equinox launching. You can disable the capability by marking it not be early start.
org.eclipse.equinox.p2.reconciler.dropins,1.0.100.v20091010,plugins/org.eclipse.equinox.p2.reconciler.dropins_1.0.100.v20091010.jar,4,false

If finding some new bundles in dorpin folder, the reconciler would add the new bundles into a local metadata repository that is stored as OSGi data of Equinox. Then synchronize the bundles into the current p2 profile, then add the new bundles into bundles.info file.

Thursday, November 12, 2009

[Eclipse][P2]Learn p2 step by step

Learn p2 step by step

Kane               

                     

p2 concept





首先来理解p2引入的几个概念[1]

  • p2 / Agent
    • The provisioning infrastructure on client machines
  • Installable Unit (IU)
    • Metadata that describes things that can be installed/configured
  • Artifact
    • The actual content being installed/configured(e.g., bundle JARs)
  • Repository
    • A store of metadata or artifacts
  • Profile
    • The target of install/management operations
  • Planner
    • The decision-making entity in the provisioning system
  • Engine
    • The mechanism for executing provisioning requests
  • Touchpoint
    • The part of the engine responsible for integrating the provisioning
      system to a particular runtime or management system
IU比较好理解,就是对可安装或配置的部分一种描述,并不对应实际要安装的文件。
Arifact就是来描述实际要安装的文件,bundle类型的jar,feature,binary文件。
这时就有了Repository(仓库)这个概念,是用来保存artifacts信息,以及artifacts的元数据。元数据包括了对artifact的唯一标识符,版本,对外暴露的接口信息,以及它依赖的接口及其版本信息,各个安装阶段需要执行的配置。在p2默认的实现里面,这两个repository用xml文件来描述,同时被压缩为artifacts.jar, content.jar来减小文件大小,缩短传输时间。
从Eclipse 3.4起,当从远程site安装新的软件时,就会看到有个work thread在后台下载content.jar文件。p2在安装时候,首先会根据content.xml(metadata repository)来解析正在安装软件的依赖。在当前runtime里面查找metadata中指定的依赖,如果满足才继续安装。据我个人经验,如果安装的软件比较复杂,那它产生的metadata文件就会比较大(很容易上兆),下载这个文件以及解析它的内容都会比较慢,从而影响用户体验。
比较灵活的是,用户可以实现自己的ArtifactRepository和MetadataRepository,注册到它们各自的Manager里面就可以了。所有这些服务都被实现为OSGi Service.
下一个Profile,是用来管理安装目标里的软件信息。p2在被设计的时候,希望解决多个eclipse实例共享一份安装的某软件。比如为了某种目的我机器上有好几个Eclipse,同时它们都需要CDT,免去为重复安装的麻烦。profile就会记录每次安装的内容,让整个应用程序被管理起来。在Galileo里安装的软件都可以软件管理里面查找到。
Planner和Engine完全就是p2内部的东西。任何p2的操作(安装,删除,配置)都需要Planner实例来描述。有了Planner以后,还需要创建一个Engine对象,通过engine来执行对应的plan。这就是目前调用p2 API来完成安装的一个过程。
最后一个Touchpoint。程序在安装的时候,可能会根据runtime(os, ws, arch等)或阶段(安装,卸载,配置等)执行某些配置,touchpoint就是帮助实现这些配置。具体操作是以IU为单位记录在metadata repository里的。p2默认实现了一些Eclipse touchpoint,比如拷贝,删除文件,执行外部程序等。如果用户有自己特殊的native操作需要执行,可以自己实现自定义的touchpoint。

p2 install

有了这些概念以后,我们来看看如何使用p2 API。以安装为例,
首先需要得到当前安装的profile。如果是全新安装,通过IProfileRegistry.addProfile创建一个新profile。是更新安装的话,可以通过IProfileRegistry查询到期望更新的profile。创建profile的时候,需要注意设置profile的属性,

Map<String, String> profileProperties = new HashMap<String, String>();
profileProperties.put(IProfile.PROP_INSTALL_FOLDER, installLocation.getAbsolutePath());
profileProperties.put(IProfile.PROP_FLAVOR, "tooling"); //$NON-NLS-1$
profileProperties.put(IProfile.PROP_ENVIRONMENTS, "osgi.os=" + Platform.getOS() + ",osgi.ws=" + Platform.getWS() + ",osgi.arch=" + Platform.getOSArch()); //$NON-NLS-1$;
profileProperties.put(IProfile.PROP_NL, "en_US"); //$NON-NLS-1$
profileProperties.put(IProfile.PROP_INSTALL_FEATURES, "true");
profileProperties.put(IProfile.PROP_CONFIGURATION_FOLDER, new File(installLocation, "configuration").getAbsolutePath());
profileProperties.put(IProfile.PROP_ROAMING, "true");
profileProperties.put(IProfile.PROP_CACHE, installLocation.getAbsolutePath());
currentProfile = registry.addProfile(PROFILE_ID, profileProperties);

PROP_INSTALL_FOLDER设置安装的目录,PROP_CACHE设置保存下载来的Eclipse IU(features/plugins)的目录,如果repository是以feature为单位来发布的话,需要设置PROP_INSTALL_FEATURES为true。如果repository包括native的binary(比如launcher)也需要指定正确的PROP_ENVIROMENTS,包括OS,WS,ARCH或PROCESSOR。
然后需要获得将要安装的IMetadataRepository集合。比如:
ArrayList<IInstallableUnit> ius = new ArrayList<IInstallableUnit>();
IMetadataRepositoryManager repositoryManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getDefault().getBundle().getBundleContext(),
IMetadataRepositoryManager.class.getName()); 
if (repositoryManager == null) 
       throw new InterruptedException("Failed to get IMetadataRepositoryManager.");
try {
  for (URI uri : uris) {

    IMetadataRepository metaRepo = repositoryManager.loadRepository(uri, progress.newChild(50/uris.length));
    Collector collector = metaRepo.query(new AccpetQuery(), new LatestNoninstalledIUCollector(currentProfile), progress.newChild(50/uris.length));

     ius.addAll(collector.toCollection());
  }
} catch (ProvisionException e) {
    throw new InterruptedException("Failed to get IMetadataRepository.");
}
     -同时这里也查找出IMetaRepository中没安装过的IUs。这就需要同当前安装的profile中已经安装过的内容来比较,
    Collector collector = metaRepo.query(new AccpetQuery(), new LatestNoninstalledIUCollector(currentProfile), progress.newChild(50/uris.length));
     这里需要指出的是,IMetadataRepository实现了IQueryable接口。IQueryable是p2引入的查找接口,返回满足特殊查询条件的集合,同时传入了一个IProgressMonitor对象,可以反应查找进度。这里的AcceptQuery,LatestNoninstalledIUCollector是自定义的Query和Collector对象。p2已经实现了许多有用的Query,经常用到的有InstallableUnitQuery,IUPropertyQuery,RangeQuery。
    -接下来生成IEngine所需的ProvisionPlan。首先创建ProfileChangeRequest对象,将先前查找出的要安装的IUs添加进去。
     request.addInstallableUnits(ius);
     删除的话则与之相反。更新的话也需要通过ProfileChangeRequest.removeInstallableUnits()去掉旧版本的IUs。
     调用IPlanner service的getProvisioningPlan(ProfileChangeRequest, ProvisioningContext, IProgressMonitor)得到对应于当前request的plan。
    -最后就是调用IEngine.perform(IProfile, PhaseSet, Operand[], ProvisioningContext, IProgressMonitor)来执行provisioning操作。这里的PhaseSet是用来指定Engine将要执行的几个阶段,以及每个阶段的执行时间权重。这些阶段包括了Collect, Unconfigure, Uninstall, Property, CheckTrust, Install, Configure. 如果熟悉Eclipse之前的Installer Handler,对Unconfigure/Uninstall/Install/Configure应该都很熟悉。 在p2里,更是将Collect, CheckTrust这些过程也暴露了出来。下面是p2里默认PhaseSet的实现,
        public DefaultPhaseSet() {
            this(new Phase[] {new Collect(100), new Unconfigure(10, forcedUninstall), new Uninstall(50, forcedUninstall), new Property(1), new CheckTrust(10), new Install(50), new Configure(10)});
        }
     Operand[]通过ProvisionPlan.getOperands()获得。





p2 install practice



先制作一个可安装的repository,这里的方法是基于Eclipse提供的模版创建一个RCP程序,比如mail template,




然后创建一个feature包含刚才创建出来的plug-in 'com.example.mail'。

基于存在的‘com.example.mail.product’创建product configuration,将其设置为base on features, 同时在dependencies页面添加以下feature。feature的qaulifier id依赖于用到的Eclipsse版本,从下图看到我这里使用的是Eclipse 3.5.1。如果要让RCP程序具有安装插件的能力(包含p2和p2 UI),就需要依赖更多的feature。后面的example里面会实现这部分功能。另外注意:ID不能包括空格字符



接下来使用Eclipse Product Export Wizard生成repository。记得要勾选上generate metadata repository。




在成功创建了Mail Application的repository后,试用我们自己的p2 installer来安装这个应用程序。安装过程类似下面的截图。然后执行/folk/kzhu0/tmp/mailrcp/mail来运行Mail Application.






p2 repository publish

这一节将会展示如何发布/产生基于p2的repository。在p2最早的版本Eclipse 3.4中将生成repository这个程序称为generator,而3.5对此重构后命名为publisher。重构后的publish过程简单明了。首先需要创建一个IPublishInfo对象,它负责提供将要生成的repository的情况。包括了meta repository, artifact repository的信息,属性,以及提供辅助信息的advice对象。IPublisherAdvice可以看作类似创建RCP窗口时候的WorkbenchAdvice和WorkbenchWindowAdvice等辅助类。它用来提供需要记录在repository中的IU特殊信息。比如IU的属性,touchpoint的类型及各个阶段执行的action,对可执行文件或配置文件IU的处理。
此外还需要创建IPublisherAction来处理不同类型的IU发布过程。例如BundlesAction来实现发布bundles到repository,FeaturesAction则是处理feature。此外p2已提供的IPublisherAction还包括product action, config action, launcher action和jre action等等[2]
有了描述repository情况的publishinfo和发布各种IUs的action后,调用Publisher.publish方法完成repository的发布。
        IPublisherInfo info = createPublisherInfo();
        IPublisherAction[] actions = createActions();
        Publisher publisher = new Publisher(info);
        publisher.publish(actions, new NullProgressMonitor());
这里有一点需要注意,publish只是把将要用于部署的features/plugins/binary发布到repository,并不负责编译打包它们。先前我们使用过Eclipse Export功能既编译打包features/plugins同时又生成repository。Export实现的过程首先是调用PDE来编译打包features/plugins,再调用对应的publisher应用程序将编译后的features/plugins/product发布为repository。


customized p2 touchpoint

前面一节已经提过IPublishInfo通过额外的IPublisherAdvise来定制发布到repository的IU信息。这里介绍为自己的IU定制新的touchpoint类型,并且要求在配置阶段在操作系统桌面创建应用程序的启动快捷方式。首先为我们的PublisherInfo添加处理touchpoint data的advice,NativeLauncherTouchPoint实现了ITouchpointAdvice接口,publisher在发布的时候当处理到touchpoint data部分,会查找实现了ITouchpointAdvice接口的advice。如果有advice可用,将会让这些advice处理现有的touchpoint data,并且得到新的touchpoint data,并把结果保存到metadata repository当中。
        PublisherInfo result = new PublisherInfo();
        result.addAdvice(new NativeLauncherTouchPoint());
NativeLauncherTouchPoint将指定为特定的IU在configure阶段执行createDesktop操作,以及相反的操作,unconfigure阶段执行deleteDesktop操作。

更改touchpoint type的方法如下。当然也可以为现有的touchpoint type扩展action。内置的touchpoint类型和action的具体命令用法,请参考p2 wiki[3]
iu.setTouchpointType(DesktopTouchpoint.TOUCHPOINT_TYPE);
touchpoint类型和action都是通过extension point来扩展的。通过扩展“org.eclipse.equinox.p2.engine.touchpoints”来添加新的touchpoint类型,扩展”org.eclipse.equinox.p2.engine.actions“将新的action同某个类型关联起来。

p2 repository publish practice

我们创建plug-in 'com.example.p2.touchpoint'来实现桌面快捷方式的扩展,并且创建'com.example.p2.feature'包含touchpoint实现的plug-in。具体实现请参考p2 example源码。
然后为Mail Application添加p2相关feature的依赖,重新发布得到支持安装软件的新版本。并且用p2 example installer安装它。p.s: 个人感觉Eclipse在包含第三方plug-in时,层次有些问题。p2作为一个runtime的project(跟equinox, ECF同级),居然需要直接或间接依赖help, rcp.platform这样的上层模块。

接下来创建plug-in 'com.example.mail.desktop' 和 feature 'com.example.mail.desktop.feature',作为提供桌面快捷方式的IU。用Eclipse Export Feature将'com.example.mail.desktop.feature'导出,实际就是用PDE替我们编译打包:)。
运行‘com.example.p2.generator'提供的headless publisher来生成我们定制的repository。’/folk/kzhu0/tmp/mail/desktop-deploy'是先前desktop feature导出后的路径,而'/folk/kzhu0/tmp/mail/desktop'是生成repository的路径。

运行新版本的Mail Application,在Help菜单下面会多出Install New Software选项。将自定义publisher生成的Desktop feature repository添加为新的软件源,安装Mail Desktop Feature。安装完成后,将在桌面找到Mail Application的快捷方式。在Installation Detail里面将会出现这次安装的内容。选中Desktop Feature后选择卸载,桌面的快捷方式文件将会被删除掉。当然也可以使用p2 example installer来为Mail Application安装desktop feature。p.s: example代码里只实现了创建linux/unix桌面快捷方式。


Example Code

Example Code应该只能编译运行在Eclipse 3.5.x。Example Code使用的都是p2 internal API, 而p2 public API将会随Eclipse 3.6首次发布。这些类和方法基本都会保留,但命名,包一定会有重构。
http://code.google.com/p/kane-toolkit/source/browse/#svn/trunk/p2-example

Reference

[1] http://wiki.eclipse.org/Equinox/p2/Concepts
[2] http://wiki.eclipse.org/Equinox/p2/Publisher
[3] http://wiki.eclipse.org/Equinox/p2/Engine/Touchpoint_Instructions