Tweetbot for Mac是MacOS X上推的不二选择,但是该软件的所有版本都没有提供Proxy设置。网上少有几篇关于Tweetbot如何使用GoAgent代理上网的教程是针对iOS平台的。

玩Ubuntu的时候有个工具软件可以作为启动器启动另一个软件,然后让被启动的软件使用该工具软件设定好的代理上网。这个工具可以解决需要使用代理上网但软件自身未提供代理配置功能的问题。

继续阅读 →

GoAgent官方推荐使用GoAgent Mac GUI或者GoAgentX作为Mac下的客户端,GoAgent Mac GUI不支持随机启动,图标太难看。GoAgentX图标和功能都不错,但是内置的goagent版本不是最新的。所有自己折腾了一下使用Mac下的LaunchAgent机制将goagent配置成自启动的后台服务。

新建plist文件

~/Library/LaunchAgents/目录里新建com.googlecode.goagent.plist文件。

继续阅读 →

其实挺简单的,官方文档也写的很清晰,不过还是碰到了让人受挫的404错误。

添加CNAME文件

echo 'your-domain.com' >> source/CNAME
继续阅读 →

本文介绍如何在MacOS X终端里使用代理访问网络,虽然只在Mountain Lion下测试,但同样适用于装有Bash的系统。

实在无法忍受linode日本机房的高延迟,动手配置了一个goagent服务。但是HTTP代理和VPN不同,没法全局代理(至少不能简单配置),在Terminal里下载最新版本的Ruby,奇慢无比,下面介绍如何让Terminal里执行的程序使用goagent代理。

继续阅读 →

本文介绍如何在终端里使用ssh命令方便的管理常用的ssh访问会话,主要针对MacOS X系统编纂,并在Mountain Lion下测试通过。但是同样适用与安装有Bash终端的*uix系统。

虽然windows没有对SSH的原生支持,但是XShellPutty都挺好用的。日常工作需要维护多台linux服务器,用户名和密码多了记不住,所有非常依赖会话记忆功能。

继续阅读 →

在项目需要从配置文件中读取一些数据, yaml的作为一种可选的非XML方案已经宣告失败, 同事给我推荐了另外两个XML的解决方案: Castor或者Digester

  • Castor是一种将Java对象和XML自动绑定的开源软件. 它可以在Java对象,XML文本,SQL数据表以及LDAP目录之间绑定.
  • Digester原是Apache Jakarta Struts计划中的一部分,用来解析Web App中的XML配置文件,在开发一段时间之后,开发人员觉得这个小工具具有很普遍的使用场合,于是,将这个部分独立出来,放到Commons项目中。

由于Digester只是支持由XML到JavaBean的单向转换,而我的项目还需要能够从JavaBean到XML的转换。 所以我选择了Castor。

下面是Castor的例子

SearchField.java
package org.scbit.lentinus.domain;
import java.util.ArrayList;
import java.util.List;
public
class SearchField {
private List<Table> tables;
public SearchField() {
this.tables = new ArrayList<Table>();
}
public List<Table> getTables() {
return
tables;
}
public
void addTable(Table table) {
this.tables.add(table);
}
}
Table.java
package org.scbit.lentinus.domain;
import java.util.ArrayList;
import java.util.List;
public
class Table {
private String tableDisplayName;
private String tableClass;
private List<Field> fields;
public Table() {
this.fields = new ArrayList<Field>();
}
public List<Field> getFields() {
return fields;
}
public void addField(Field field) {
this.fields.add(field);
}
public String getTableClass() {
return tableClass;
}
public void setTableClass(String tableClass) {
this.tableClass = tableClass;
}
public String getTableDisplayName() {
return tableDisplayName;
}
public void setTableDisplayName(String tableDisplayName) {
this.tableDisplayName = tableDisplayName;
}
}
Field.java
package org.scbit.lentinus.domain;
public
class Field {
public Field() {
}
private String fieldDisplay;
private String fieldName;
public String getFieldDisplay() {
return fieldDisplay;
}
public void setFieldDisplay(String fieldDisplay) {
this.fieldDisplay = fieldDisplay;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}

转换代码

@Test
public void testField() throws Exception {
SearchField searchField = new SearchField();
Table table;
Field field;
table = new Table();
table.setTableDisplayName("级别信息");
table.setTableClass("TbBasicInfor");
field = new Field();
field.setFieldDisplay("拉丁学名");
field.setFieldName("latinName");
table.addField(field);
field = new Field();
field.setFieldDisplay("拉丁别名");
field.setFieldName("latinAlias");
table.addField(field);
searchField.addTable(table);
// write it out as XML
File file = new File(
"D:\\dev\\workplace\\eclipse_workspace\\LentinusEdodes\\WebRoot\\WEB-INF\\conf\\searchField.xml");
Writer writer = new OutputStreamWriter(new FileOutputStream(file),
"utf-8");
Marshaller marshaller = new Marshaller(writer);
marshaller.setEncoding("utf-8"); // 关键
marshaller.marshal(searchField);
// now restore the value and list what we get
Reader reader = new InputStreamReader(new FileInputStream(file),
"utf-8");
SearchField read = (SearchField) Unmarshaller.unmarshal(
SearchField.class, reader);
assertTrue(read.getTables().get(0).getTableDisplayName().equals("级别信息"));
writer.close();
reader.close();
}

转换后的XML文件

searchField.xml

<?xml version="1.0" encoding="utf-8"?>
<search-field>
<tables xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="java:org.scbit.lentinus.domain.Table">
<fields xsi:type="java:org.scbit.lentinus.domain.Field">
<field-display>拉丁学名</field-display>
<field-name>latinName</field-name>
</fields>
<fields xsi:type="java:org.scbit.lentinus.domain.Field">
<field-display>拉丁别名</field-display>
<field-name>latinAlias</field-name>
</fields>
<table-class>TbBasicInfor</table-class>
<table-display-name>级别信息</table-display-name>
</tables>
</search-field>

Castor使用起来还是比较简单的,但在读取中文的时候,要注意可能会有乱码问题,在它官方的FAQ中有相应的解释和解决方法。 > How do I set the encoding? Create a new instance of the Marshaller class and use the setEncoding method. You’ll also need to make sure the encoding for the Writer is set properly as well: … String encoding = “ISO-8859-1”; FileOutputStream fos = new FileOutputStream(“result.xml”); OutputStreamWriter osw = new OuputStreamWriter(fos, encoding); Marshaller marshaller = new Marshaller(osw); marshaller.setEncoding(encoding); …

参考文章

  1. XML 与 Java 技术: 用 Castor 进行数据绑定
  2. Castor JDO 入门
  3. 学习Digester笔记

前不久在《程序员》上看到了关于Yaml的介绍。 据说是现在Ruby下用的很火的配置文件。 在其官方站点有其对文件格式的一些简单介绍。 在sourceforge上也有两个开源的yaml配置文件的解析包JYaml和Yaml4J 另外在dev.java.net上有另一个解析包Jvyaml,由于找不到文档就没有进一步的研究。

公司的最近的一个项目需要从配置文件中读取结构化的数据,需要一个POJO类的反序列化。 于是迫不及待的想体验新技术, 虽然我不是第一个吃螃蟹的,但还是付出了不少的代价。

Yaml4J比较弱一点,只提供了Loader/Dumper方法。 相比之下,JYaml的提供的序列化和反序列化的方法多多了, 而且不但支持List和Map这两种yaml中主要的数据结构, 还支持Date,String,Double,BigInteger 和BigDecimal, 特别是它支持javabean的反序列化。

于是我在eclipse下写了一个官方提供的例子。简单的测试,一切运行正常。

下面是我项目中的例子:

SearchField.java
package org.scbit.lentinus.domain;
public class SearchField {
private Table[] tables;
public Table[] getTables() {
return tables;
}
public void setTables(Table[] tables) {
this.tables = tables;
}
}
Table.java
package org.scbit.lentinus.domain;
import java.io.UnsupportedEncodingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Table {
private static Log log = LogFactory.getLog(Table.class);
private String tableDisplayName;
private String tableClass;
private Field[] fields;
public Field[] getFields() {
return fields;
}
public void setFields(Field[] fields) {
this.fields = fields;
}
public String getTableClass() {
return tableClass;
}
public void setTableClass(String tableClass) {
this.tableClass = tableClass;
}
public String getTableDisplayName() {
return tableDisplayName;
}
public void setTableDisplayName(String tableDisplayName) {
try {
this.tableDisplayName = new String(tableDisplayName.getBytes(),
"utf-8");
} catch (UnsupportedEncodingException e) {
log.error("Table.setTableDisplayName UnsupportedEncodingException");
e.printStackTrace();
}
}
}
Field.java
package org.scbit.lentinus.domain;
import java.io.UnsupportedEncodingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Field {
private static Log log = LogFactory.getLog(Field.class);
public Field() {
}
private String fieldDisplay;
private String fieldName;
public String getFieldDisplay() {
return fieldDisplay;
}
public void setFieldDisplay(String fieldDisplay) {
try {
this.fieldDisplay = new String(fieldDisplay.getBytes(), "utf-8");
} catch (UnsupportedEncodingException e) {
log.error("Field.setFieldDisplay UnsupportedEncodingException");
e.printStackTrace();
}
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}
searchField.yml
tables:
- tableDisplayName: 基本信息
tableClass: TbBasicInfor
fields:
- fieldDisplay: 拉丁学名
fieldName: latinName
- fieldDisplay: 拉丁别名
fieldName: latinAlias
- fieldDisplay: 中文名
fieldName:chineseName
- fieldDisplay:中文别名
fieldName:chineseAlias
- fieldDispaly:品种代号
fieldName:speciesCode
- fieldDispaly:来源单位
fieldName:sourceCompany
- tableDisplayName:育种者
tableClass:TbCultivator
fields:
- fieldDisplay:育种者姓名
fieldName:cultivator
- fieldDisplay:单位
fieldName:cultivationCompany
- fieldDisplay:地址
fieldName:cultivationAddress
- fieldDisplay:电话
fieldName:telephone
- fieldDisplay:邮编
fieldName:zipCode
- fieldDisplay:鉴定单位
fieldName:appraisalOrganization
- fieldDisplay:获奖
fieldName:award
- fieldDisplay:应用
fieldName:application
- tableDisplayName:菌落
tableClass:TbColony
fields:
- fieldDisplay:菌丝被膜的形成
fieldName:myceliumCapsule
- fieldDisplay:菌丝密度
fieldName:myceliumDensity
- fieldDisplay:菌落表面颜色
fieldName:surfaceColor
- fieldDisplay:拮抗现象
fieldName:antagonisticPhenomenon

下面是测试代码:

@Test
public void testField() throws Exception {
File yamlfile = new File(
"D:\\dev\\workplace\\eclipse_workspace\\LentinusEdodes\\src\\test\\org\\scbit\\lentinus\\domain\\searchField.yml");
SearchField obj = Yaml.loadType(yamlfile, SearchField.class);
System.out.println(obj.getTables()[0].getFields()[0].getFieldName());
String str = obj.getTables()[0].getFields()[1].getFieldDisplay();
System.out.println(new String(str.getBytes(), "gbk"));
}

测试结果:

latinName
java.lang.ArrayIndexOutOfBoundsException: 1
at org.scbit.lentinus.domain.TestSearchField.testField(TestSearchField.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:71)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

JYaml在解析多层嵌套的数据结构的时候有问题, 具体来说,在层次结构较深时Array只能解析出第一元素,即[0]。 但这个在解析时并不会抛出错误。 这个问题至今没有解决。 我使用的JYaml版本是jyaml-lib-14-1.0-beta-3.jar 不知道是我的配置文件写得有问题,还是beta般的bug。

另外在中文支持方面也有所欠缺,直接读取utf-8格式的中文会出现乱码,需要自己转码: this.fieldDisplay = new String(fieldDisplay.getBytes(), “utf-8”); 当然你也可以帮你的yml文件的格式改为iso-8859-1不过在这种编码状态下你的中文是乱码。 希望今后的版本能有所改进。

看了一些使用html:link的文章,大多只是说了paramId结合paramName和paramProperty的使用。下面将会用到name,paramId,paramName和paramProperty一起使用的效果。

继续阅读 →

winxp sp2 的早期版本5.1.2600.2055 (xpsp_sp2_beta1.031215-1745)可以配置成远程界面多用户访问。本文介绍通过替换系统文件termsrv.dll的方式让正式版本的winxp sp2支持多用户远程登录。

下面的脚步是用来进行文件替换,注册表修改等相关配置的, 将分隔线中的代码拷贝到记事本中,重命名为clickme.cmd, 然后放到与termsrv.dll同一目录双击运行即可。 记得要重启电脑哦。

rem 修改注册表值
@echo off
setlocal
set regkey="HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\Licensing Core"
reg add %regkey% /v EnableConcurrentSessions /T REG_DWORD /D 1 /f
endlocal
rem 替换termsvr.dll文件
mkdir .\temp
copy .\termsrv.dll .\temp\termsrv.dll
replace .\temp\termsrv.dll %windir%\system32\dllcache
del /Q .\temp\termsrv.dll
copy .\termsrv.dll .\temp\termsrv.dll
TASKKILL /F /FI "MODULES eq termsrv.dll"
shutdown -a
replace .\temp\termsrv.dll %windir%\system32  
del /Q .\temp\termsrv.dll
rmdir /Q .\temp
rem 启动相关系统服务
call %windir%\system32\svchost.exe -k DComLaunch
call %windir%\system32\svchost.exe -k netsvcs

相关文件下载

termsrv.dll

参考文章

  1. 打开 XP Pro SP2 远程桌面的多用户支持 Enable Concurrent Sessions

载入functions taglib <%@ taglib uri=”http://java.sun.com/jsp/jstl/functions” prefix=”fn”%>

计算collection的size ${fn:length(your_collction)}

length函数的描述如下

fn.tld
<function>
<description>
Returns the number of items in a collection, or the number of characters in a string.
</description>
<name>length</name>
<function-class>org.apache.taglibs.standard.functions.Functions</function-class>
<function-signature>int length(java.lang.Object)</function-signature>
<example>
You have ${fn:length(shoppingCart.products)} in your shopping cart.
</example>
</function>