Archive for the ‘Computers and Internet’ Category

AspectJ切入点语法详解   Leave a comment

http://jinnianshilongnian.iteye.com/blog/1415606

6.5  AspectJ切入点语法详解

6.5.1  Spring AOP支持的AspectJ切入点指示符

切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下:

execution用于匹配方法执行的连接点;

         within用于匹配指定类型内的方法执行;

         this用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;

         target用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

         args用于匹配当前执行的方法传入的参数为指定类型的执行方法;

         @within用于匹配所以持有指定注解类型内的方法

         @target用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;

         @args用于匹配当前执行的方法传入的参数持有指定注解的执行;

         @annotation用于匹配当前执行方法持有指定注解的方法;

         beanSpring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;

         reference pointcut表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

AspectJ切入点支持的切入点指示符还有: call、get、set、preinitialization、staticinitialization、initialization、 handler、adviceexecution、withincode、cflow、cflowbelow、if、@this、 @withincode;但Spring AOP目前不支持这些指示符,使用这些指示符将抛出IllegalArgumentException异常。这些指示符Spring AOP可能会在以后进行扩展。

6.5.1  命名及匿名切入点

命名切入点可以被其他切入点引用,而匿名切入点是不可以的。

只有@AspectJ支持命名切入点,而Schema风格不支持命名切入点。

如下所示,@AspectJ使用如下方式引用命名切入点:

6.5.2        ;类型匹配语法

首先让我们来了解下AspectJ类型匹配的通配符:

*:匹配任何数量字符;

..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

+匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

 


java代码:

  1. java.lang.String    匹配String类型;
  2. java.*.String       匹配java包下的任何“一级子包”下的String类型;
  3. 如匹配java.lang.String,但不匹配java.lang.ss.String
  4. java..*            匹配java包及任何子包下的任何类型;
  5.                   如匹配java.lang.String、java.lang.annotation.Annotation
  6. java.lang.*ing      匹配任何java.lang包下的以ing结尾的类型;
  7. java.lang.Number+  匹配java.lang包下的任何Number的自类型;
  8.                    如匹配java.lang.Integer,也匹配java.math.BigInteger



接下来再看一下具体的匹配表达式类型吧:

匹配类型:使用如下方式匹配

 

 

java代码:

  1. 注解? 类的全限定名字
  • 注解:可选,类型上持有的注解,如@Deprecated;
  • 类的全限定名:必填,可以是任何类全限定名。

匹配方法执行:使用如下方式匹配:

 

 

java代码:

  1. 注解? 修饰符? 返回值类型 类型声明?方法名(参数列表) 异常列表?

 

 

  • 注解:可选,方法上持有的注解,如@Deprecated;
  • 修饰符:可选,如public、protected;
  • 返回值类型:必填,可以是任何类型模式;“*”表示所有类型;
  • 类型声明:可选,可以是任何类型模式;
  • 方法名:必填,可以使用“*”进行模式匹配;
  • 参数列表:“()”表示方法没有任何参数;“(..)”表示匹配接受任意个参数的方 法,“(..,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方 法;“(java.lang.String,..)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;
  • 异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。

匹配Bean名称:可以使用Bean的id或name进行匹配,并且可使用通配符“*”;

6.5.3  组合切入点表达式

AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。

在Schema风格下,由于在XML中使用“&&”需要使用转义字符“&&”来代替之,所以很不方便,因此Spring ASP 提供了and、or、not来代替&&、||、!。

 

6.5.3  切入点使用示例

       一、execution使用“execution(方法表达式)”匹配方法执行;

 

模式 描述
public * *(..) 任何公共方法的执行
* cn.javass..IPointcutService.*() cn.javass包及所有子包下IPointcutService接口中的任何无参方法
* cn.javass..*.*(..) cn.javass包及所有子包下任何类的任何方法
* cn.javass..IPointcutService.*(*) cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
* (!cn.javass..IPointcutService+).*(..) 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
* cn.javass..IPointcutService+.*() cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
* cn.javass..IPointcut*.test*(java.util.Date) cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的

如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;

* cn.javass..IPointcut*.test*(..)  throws

IllegalArgumentException, ArrayIndexOutOfBoundsException

cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
* (cn.javass..IPointcutService+

&& java.io.Serializable+).*(..)

任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
@java.lang.Deprecated * *(..) 任何持有@java.lang.Deprecated注解的方法
@java.lang.Deprecated @cn.javass..Secure  * *(..) 任何持有@java.lang.Deprecated和@cn.javass..Secure注解的方法
@(java.lang.Deprecated || cn.javass..Secure) * *(..) 任何持有@java.lang.Deprecated或@ cn.javass..Secure注解的方法
(@cn.javass..Secure  *)  *(..) 任何返回值类型持有@cn.javass..Secure的方法
*  (@cn.javass..Secure *).*(..) 任何定义方法的类型持有@cn.javass..Secure的方法
* *(@cn.javass..Secure (*) , @cn.javass..Secure (*)) 任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,

如public void test(@Secure String str1,

@Secure String str1);

* *((@ cn.javass..Secure *))或

* *(@ cn.javass..Secure *)

任何带有一个参数的方法,且该参数类型持有@ cn.javass..Secure;

如public void test(Model model);且Model类上持有@Secure注解

* *(

@cn.javass..Secure (@cn.javass..Secure *) ,

@ cn.javass..Secure (@cn.javass..Secure *))

任何带有两个参数的方法,且这两个参数都被@ cn.javass..Secure标记了;且这两个参数的类型上都持有@ cn.javass..Secure;

 

* *(

java.util.Map<cn.javass..Model, cn.javass..Model>

, ..)

任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass..Model, cn.javass..Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;

如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(

java.util.HashMap<cn.javass..Model,cn.javass..Model>

, ..)”进行匹配;

而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配

* *(java.util.Collection<@cn.javass..Secure *>) 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;

如public void test(Collection<Model> collection);Model类型上持有@cn.javass..Secure

* *(java.util.Set<? extends HashMap>) 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承与HashMap;

Spring AOP目前测试不能正常工作

* *(java.util.List<? super HashMap>) 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map);

Spring AOP目前测试不能正常工作

* *(*<@cn.javass..Secure *>) 任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;

Spring AOP目前测试不能正常工作

 

within:使用“within(类型表达式)匹配指定类型内的方法执行;

模式 描述
within(cn.javass..*) cn.javass包及子包下的任何方法执行
within(cn.javass..IPointcutService+) cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
within(@cn.javass..Secure *) 持有cn.javass..Secure注解的任何类型的任何方法

必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

 

this使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符;

 

模式 描述
this(cn.javass.spring.chapter6.service.IPointcutService) 当前AOP对象实现了 IPointcutService接口的任何方法
this(cn.javass.spring.chapter6.service.IIntroductionService) 当前AOP对象实现了 IIntroductionService接口的任何方法

也可能是引入接口

 

 

 

 

 

 

四、target使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符;

模式 描述
target(cn.javass.spring.chapter6.service.IPointcutService) 当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
target(cn.javass.spring.chapter6.service.IIntroductionService) 当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法

不可能是引入接口

 

 

 

 

 

 

 

 

五、args使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;

模式 描述
args (java.io.Serializable,..) 任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的

 

 

 

 

 

 

六、@within使用“@within(注解类型)”匹配所以持有指定注解类型内的方法;注解类型也必须是全限定类型名;

模式 描述
@within cn.javass.spring.chapter6.Secure) 任何目标对象对应的类型持有Secure注解的类方法;

必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

 

 

 

 

 

 

七、@target使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名; 

 

模式 描述
@target (cn.javass.spring.chapter6.Secure) 任何目标对象持有Secure注解的类方法;

必须是在目标对象上声明这个注解,在接口上声明的对它不起作用

 

 

 

 

 

 

八、@args使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名;

模式 描述
@args (cn.javass.spring.chapter6.Secure) 任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;

 

 

 

 

 

 

九、@annotation使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名;

模式 描述
@annotation(cn.javass.spring.chapter6.Secure ) 当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配

 

 

 

 

 

十、bean使用“bean(Bean id或名字通配符)匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念;

模式 描述
bean(*Service) 匹配所有以Service命名(id或name)结尾的Bean

 

 

 

 

十一、reference pointcut表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持,如下所示:

 

      

       比如我们定义如下切面:

 

java代码:

  1. package cn.javass.spring.chapter6.aop;
  2. import org.aspectj.lang.annotation.Aspect;
  3. import org.aspectj.lang.annotation.Pointcut;
  4. @Aspect
  5. public class ReferencePointcutAspect {
  6.     @Pointcut(value=”execution(* *())”)
  7.     public void pointcut() {}
  8. }

 

 

可以通过如下方式引用:

 


java代码:

  1. @Before(value = “cn.javass.spring.chapter6.aop.ReferencePointcutAspect.pointcut()”)
  2. public void referencePointcutTest2(JoinPoint jp) {}


除了可以在@AspectJ风格的切面内引用外,也可以在Schema风格的切面定义内引用,引用方式与@AspectJ完全一样。

 

到此我们切入点表达式语法示例就介绍完了,我们这些示例几乎包含了日常开发中的所有情况,但当然还有更复杂的语法等等,如果以上介绍的不能满足您的需要,请参考AspectJ文档。

由于测试代码相当长,所以为了节约篇幅本示例代码在cn.javass.spring.chapter6. PointcutTest文件中,需要时请参考该文件。

6.6  通知参数

前边章节已经介绍了声明通知,但如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式。

  • 使用JoinPoint获取:Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的第一个参数都可以是JoinPoint(环绕通 知是ProceedingJoinPoint,JoinPoint子类),当然第一个参数位置也可以是JoinPoint.StaticPart类型,这 个只返回连接点的静态部分。

1) JoinPoint提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:

 

 

java代码:

  1. package org.aspectj.lang;
  2. import org.aspectj.lang.reflect.SourceLocation;
  3. public interface JoinPoint {
  4.     String toString();         //连接点所在位置的相关信息
  5.     String toShortString();     //连接点所在位置的简短相关信息
  6.     String toLongString();     //连接点所在位置的全部相关信息
  7.     Object getThis();         //返回AOP代理对象
  8.     Object getTarget();       //返回目标对象
  9.     Object[] getArgs();       //返回被通知方法参数列表
  10.     Signature getSignature();  //返回当前连接点签名
  11.     SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
  12.     String getKind();        //连接点类型
  13.     StaticPart getStaticPart(); //返回连接点静态部分
  14. }

 

 

 

2ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法:


java代码:

  1. public interface ProceedingJoinPoint extends JoinPoint {
  2.     public Object proceed() throws Throwable;
  3.     public Object proceed(Object[] args) throws Throwable;
  4. }


 

3) JoinPoint.StaticPart提供访问连接点的静态部分,如被通知方法签名、连接点类型等:

 

java代码:

  1. public interface StaticPart {
  2. Signature getSignature();    //返回当前连接点签名
  3. String getKind();          //连接点类型
  4.     int getId();               //唯一标识
  5. String toString();         //连接点所在位置的相关信息
  6.     String toShortString();     //连接点所在位置的简短相关信息
  7.     String toLongString();     //连接点所在位置的全部相关信息
  8. }

 

使用如下方式在通知方法上声明,必须是在第一个参数,然后使用jp.getArgs()就能获取到被通知方法参数:

 

 

 

java代码:

  1. @Before(value=”execution(* sayBefore(*))”)
  2. public void before(JoinPoint jp) {}
  3. @Before(value=”execution(* sayBefore(*))”)
  4. public void before(JoinPoint.StaticPart jp) {}

 

  • 自动获取:通过切入点表达式可以将相应的参数自动传递给通知方法,例如前边章节讲过的返回值和异常是如何传递给通知方法的。

在Spring AOP中,除了execution和bean指示符不能传递参数给通知方法,其他指示符都可以将匹配的相应参数或对象自动传递给通知方法。

 

 

java代码:

  1. @Before(value=”execution(* test(*)) && args(param)”, argNames=”param”)
  2. public void before1(String param) {
  3.     System.out.println(“===param:” + param);
  4. }

 

 

 

切入点表达式execution(* test(*)) && args(param) :

1)首先execution(* test(*))匹配任何方法名为test,且有一个任何类型的参数;

2)args(param)将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型,即java.lang.String;如果匹配将把该被通知参数传递给通知方法上同名参数。

其他指示符(除了execution和bean指示符)都可以使用这种方式进行参数绑定。

在此有一个问题,即前边提到的类似于【3.1.2构造器注入】中的参数名注入限制:class文件中没生成变量调试信息是获取不到方法参数名字的。

所以我们可以使用策略来确定参数名:

  1. 如果我们通过“argNames”属性指定了参数名,那么就是要我们指定的;

 

java代码:

  1. @Before(value=” args(param)”, argNames=”param”) //明确指定了
  2. public void before1(String param) {
  3.     System.out.println(“===param:” + param);
  4. }

 

  1. 如果第一个参数类型是JoinPoint、ProceedingJoinPoint或JoinPoint.StaticPart类型,应该从“argNames”属性省略掉该参数名(可选,写上也对),这些类型对象会自动传入的,但必须作为第一个参数;

 

java代码:

  1. @Before(value=” args(param)”, argNames=”param”) //明确指定了
  2. public void before1(JoinPoint jp, String param) {
  3.     System.out.println(“===param:” + param);
  4. }

 

  1. 如果“class文件中含有变量调试信息”将使用这些方法签名中的参数名来确定参数名;

 

java代码:

  1. @Before(value=” args(param)”) //不需要argNames了
  2. public void before1(JoinPoint jp, String param) {
  3.     System.out.println(“===param:” + param);
  4. }

 

  1. 如果没有“class文件中含有变量调试信息”,将尝试自己的参数匹配算法,如果发现参数绑定有二义性将抛出AmbiguousBindingException异常;对于只有一个绑定变量的切入点表达式,而通知方法只接受一个参数,说明绑定参数是明确的,从而能配对成功。

 

java代码:

  1. @Before(value=” args(param)”)
  2. public void before1(JoinPoint jp, String param) {
  3.     System.out.println(“===param:” + param);
  4. }

 

  1. 以上策略失败将抛出IllegalArgumentException。

接下来让我们示例一下组合情况吧:

 

 

 

java代码:

  1. @Before(args(param) && target(bean) && @annotation(secure)”,
  2.         argNames=”jp,param,bean,secure”)
  3. public void before5(JoinPoint jp, String param,
  4.  IPointcutService pointcutService, Secure secure) {
  5. ……
  6. }

 

该示例的执行步骤如图6-5所示。

图6-5 参数自动获取流程

 

除了上边介绍的普通方式,也可以对使用命名切入点自动获取参数:

 

 

java代码:

  1. @Pointcut(value=”args(param)”, argNames=”param”)
  2. private void pointcut1(String param){}
  3. @Pointcut(value=”@annotation(secure)”, argNames=”secure”)
  4. private void pointcut2(Secure secure){}
  5. @Before(value = “pointcut1(param) && pointcut2(secure)”,
  6.  argNames=”param, secure”)
  7. public void before6(JoinPoint jp, String param, Secure secure) {
  8. ……
  9. }

 

自此给通知传递参数已经介绍完了,示例代码在cn.javass.spring.chapter6.ParameterTest文件中。

 

 

 

 

在Spring配置文件中,所以AOP相关定义必须放在<aop:config>标签下,该标签下可以 有<aop:pointcut>、<aop:advisor>、<aop:aspect>标签,配置顺序不可变。

  • <aop:pointcut>:用来定义切入点,该切入点可以重用;
  • <aop:advisor>:用来定义只有一个通知和一个切入点的切面;
  • <aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的;和advisor的区别就在此,advisor只包含一个通知和一个切入点。

 

Posted 2012年05月24日 by gw8310 in java

XMLGregorianCalendar and Date   Leave a comment

Date –> XMLGregorianCalendar

GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

 

XMLGregorianCalendar  –> Date

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();

Posted 2012年05月14日 by gw8310 in java

Tagged with ,

KB MB GB TB PB EB ZB YB   Leave a comment

KB Kilobyte 1,024 Bytes
MB Megabyte 1,048,576 Bytes
Gb Gigabit 1 million bits
GB Gigabyte 1,073,741,824 Bytes | One billion Bytes
TB Terrabyte 1024 GB, 1,048,576 MB, 8,388,608 KB, 1,099,511,627,776 Bytes and 8,796,093,022,208 bits.
PB Pettabyte 1024 TB, 1,048,576 GB, 1,073,741,824 MB, 1,099,511,627,776 KB, 1,125,899,906,842,624 Bytes and 9,007,199,254,740,992 bits.
EB Exabyte 1024 PB, 1,048,576 TB, 1,073,741,824 GB, 1,099,511,627,776 MB, 1,125,899,906,842,624 KB, 1,152,921,504,606,846,976 Bytes and 9,223,372,036,854,775,808 bits.
ZB Zettabyte 1024 EB, 1,048,576 PB, 1,073,741,824 TB, 1,099,511,627,776 GB, 1,125,899,906,842,624 MB, 1,152,921,504,606,846,976 KB, 1,180,591,620,717,411,303,424 Bytes and 9,444,732,965,739,290,427,392 bits
YB Yottabyte 1024 ZB, 1,048,576 EB, 1,073,741,824 PB, 1,099,511,627,776 TB, 1,125,899,906,842,624 GB, 1,152,921,504,606,846,976 MB, 1,180,591,620,717,411,303,424 KB 1,208,925,819,614,629,174,706,176 Bytes and 9,671,406,556,917,033,397,649,408 bits

Posted 2012年04月30日 by gw8310 in other

Apex bulk Trigger   Leave a comment

Bulk Trigger

Tigger on the child sobject.

to make a set<ParentID> from Trigger.New,
to make a Map<Id, Parent> by new Map([select XX from ParentSObject where id : set<ParentId>])
to loop the child sobject,
first: get parentid from child sobject.
second: using map to get parent sobject.
now you can get parent sobject(with fields you want) and child sobject(with the fields you want).

 

to make a parent id set by Trigger.oldMap.KeySet();
to get the list of child sobject by querying the child sobject [select XXX from childSObject where parentId in :set<ParentId>]
to loop the child sobject list
get parent sobject record by Trigger.oldMap.get(childSobjectRecord.parentId)
do something….

Posted 2012年04月24日 by gw8310 in salesforce

Tagged with , , ,

ini file   Leave a comment

为什么要用INI文件?如果我们程序没有任何配置文件时,这样的程序对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,这样很不好,所以要用配置文件,让程序出厂后还能根据需要进行必要的配置;配置文件有很多如INI配置文件,XML配置文件,还有就是可以使用系统注册表等。

本文主要是为读者在实现读写INI配置文件模块之前,提供有关INI文件的格式信息。

在早期的windows桌面系统中主要是用INI文件作为系统的配置文件,从win95以后开始转向使用注册表,但是还有很多系统配置是使用INI文件的。其实INI文件就是简单的text文件,只不过这种txt文件要遵循一定的INI文件格式。现在的WINCE系统上也常常用INI文件作为配置文件,这次研究INI文件的目的就是为了我的GPS定位系统客户端写个系统配置文件。“.INI ”就是英文 “initialization”的头三个字母的缩写;当然INI file的后缀名也不一定是”.ini”也可以是”.cfg”,”.conf ”或者是”.txt”。

 

经典格式:

INI文件的格式很简单,最基本的三个要素是:parameters,sections和comments。

什么是parameters?

INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,name和value是由等号“=”隔开。name在等号的左边。

如:

name = value

什么是sections ?

所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。

section如下所示:

[section]

 

什么是comments ?

在INI文件中注释语句是以分号“;”开始的。所有的所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。

注释实例如下:

;comments text

 

当然,上面讲的都是最经典的INI文件格式,随着使用的需求INI文件的格式也出现了很多变种;

 

http://en.wikipedia.org/wiki/INI_file

 

http://stackoverflow.com/questions/190629/what-is-the-easiest-way-to-parse-an-ini-file-in-java

 

The library I’ve used is ini4j. It is lightweight and parses the ini files with ease. Also it uses no esoteric dependencies to 10,000 other jar files, as one of the design goals was to use only the standard Java API

This is an example on how the library is used:

 

ferences prefs = new IniFile(new File(filename));
System.out.println("grumpy/homePage: " + prefs.node("grumpy").get("homePage", null));

As mentionedini4j  can be used to achieve this. Let me show one other example.

If we have an INI file like this:

[header]
key = "value"

The following should display “value” to STDOUT:

Ini ini = new Ini(new File("/path/to/file"));
System.out.println(ini.get("header", "key"));

Check the tutorial  for more examples.

http://ini4j.sourceforge.net/tutorial/OneMinuteTutorial.java.html


Posted 2012年04月12日 by gw8310 in ini, java

Tagged with ,

常用的dos命令   Leave a comment

静默删除

del /f /s /q filename

multiple commands in CMD
& 
 command1 & command2 
 Execute Command1 and then execute Command2

&& 
 command1 && command2
 Runs the command2 only when command1 doesn't Complete successfully

|| 
 command1 || command2
 Runs the second command if the first command had an error

() 
 (command1 || command2) || (command3 & command4) 
 Defines the order in which commands are to be executed

Posted 2012年04月6日 by gw8310 in dos

How do I share an Eclipse User Library with other users?   Leave a comment

http://www.avajava.com/tutorials/lessons/how-do-i-share-an-eclipse-user-library-with-other-users.html

http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fpreferences%2Fjava%2Fbuildpath%2Fref-preferences-user-libraries.htm

 

 

An EclipseSW User Library can be used to group a set of jarW files, such as a set of TomcatSW jar files. In another tutorial, I created a user library called “TOMCAT_6.0.14_LIBRARY” for a set of Tomcat jar files.

In a group development setting, it can be useful to share a user library with other developers so that all developers can can gain the benefits of using a user library classpathW. It’s beneficial for all developers to use the same user library so as to avoid jar file dependency issues.

You can share a user library with other developers by exporting your user library to an XMLW file. This XML file can then be imported by other developers.

To export a user library, to go Window → Preferences and go to JavaSW → Build Path → User Libraries. Here, click the Export button.

Export User Library

Select the user library or libraries to export. I selected the TOMCAT_6.0.14_LIBRARY library. Enter a destination location and name. I chose to export the file to my desktop and named the file “tomcat_6.0.14_library.xml”. Click OK. Your user library should now be exported to a file.

Export User Library

The generated tomcat_6.0.14_library.xml file is shown below:

tomcat_6.0.14_library.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<eclipse-userlibraries version="2">
    <library name="TOMCAT_6.0.14_LIBRARY" systemlibrary="false">
        <archive path="C:/dev/apache-tomcat-6.0.14/bin/bootstrap.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/bin/commons-daemon.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/bin/tomcat-juli.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/annotations-api.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/catalina.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/catalina-ant.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/catalina-ha.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/catalina-tribes.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/el-api.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/jasper.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/jasper-el.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/jasper-jdt.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/jsp-api.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/servlet-api.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/tomcat-coyote.jar"/>
        <archive path="C:/dev/apache-tomcat-6.0.14/lib/tomcat-dbcp.jar"/>
    </library>
</eclipse-userlibraries>

One important thing to notice is that the archive paths (the paths to the jar files) in the xmlW file are paths to the various jar files in the file system. If the other developers on your team are using the same location for Tomcat (C:/dev/apache-tomcat-6.0.14/), then they don’t need to alter the file before importing the User Library. If their Tomcat installations are in a different location, then this file needs to be updated to contain the paths to their Tomcat installations before they import the file.

As a final note, the user library can be imported via the Import button at Java → Build Path → User Libraries.

Posted 2012年04月3日 by gw8310 in eclipse

关于 shell 脚本编程的10 个最佳实践   Leave a comment

http://www.iteye.com/news/24742

http://unix-school.blogspot.in/2012/03/10-good-shell-scripting-practices.html

 

每一个在UNIX/Linux上工作的程序员可能都擅长shell脚本编程。但大家解决问题的方式却不尽相同,这要取决于对专业知识的掌握程度、使用命令的种类、看待问题的方式等等。对于那些处在shell脚本编程初级阶段的程序员来说,遵循一些恰当的做法可以帮助你更快、更好的学习这些编程技巧。下面,我们就来讨论这些能帮助你学习shell脚本编程的方法吧。

1、多动手

你想学习shell脚本编程,这很不错。于是你拿了一本书开始学习。一些人会首先通读整本教材后再上机练习。这种方法可能适用于一些人,但我却不太看好它。我的建议是,仅仅学一些最基础的能够让你开始编码的知识就可以了。之后,动手写一些简单的程序吧。一旦你由于知识上的欠缺而不得不停止时,再回到书本上去读你想要了解的那部分,然后继续做你的项目。如此周而复始,不断提高你的水平。这种边学边做的方法曾让我受益良多。

2、善用命令提示符

有时候,我们写的脚本中有一些错误。我们修改错误,运行脚本,但系统再次报错。并且这个改错报错的过程可能会发生很多次。碰到这些情况,首先需要找到有问题的行或命令,这可以通过一些调试语句来轻松做到。一旦发现这条语句,尝试在命令提示符下执行相同的语句。如果它在命令提示符下开始正常运行,你就可以容易的推断出它不能正常运行的原因了。可能是由于某些错误输入的命令,或者是某些环境变量不匹配,或者是从不同的地方引用了某个二进制文件等等。这种方法会让调试变得简单易行。

3、考虑问题要全面

现在我们来看个问题。你想到了关于某个问题的解决方案,但这个解决方案只适用于处理小型文件。可是当处理比较大的文件时,你该怎么办?举个例子,我们想要得到一个文件的第一行内容:
代码
sed -n ‘1p’ file

这条语句当然会给出你想要的第一行内容。可是如果处理的文件包含上百万条记录呢?尽管上面的那条sed命令可以输出文件的第一行内容,但是想要处理大型文件一定会带来性能上的问题。

解决办法:
代码
sed -n ‘1p;1q’ file

这条命令将只输出第一行,同时退出程序。

4、经常尝试不同的方法

你在写脚本时碰到一个问题,然后你找到了一种独特的解决方法。下一次你偶然又碰到类似的问题,这时,不要再用以前你用过的方法来解决。试试另外一种方法吧。如果某一天再次遇到这种情况,再试试其它方法。
例如:
代码
if [ $? -eq 0 ]
then
echo “Success”
fi

另一种方法:
代码
[ $? -eq 0 ] && echo “Success”

现在你可能会明白这个博客里会有那么多以“……的不同解决方法”为题的文章了吧。所有这些文章的目的都是用来帮助订阅这个博客的开发者开阔视野,打开思路。

5、快速编码

脚本可以节省我们的时间,提高生产力。可是,难道我们花在写脚本和测试上的时间还少吗?我们想写一个脚本,于是打开一个文件,写下代码,保存文件,之后运行脚本,系统报错,我们再打开文件修改、保存、运行……在这个过程中会花费很多时间。在此前的一篇题为《如何快速写shell脚本》的文章里,你可以学会如何编写脚本和测试正在运行中的脚本,而不用再回顾命令提示符。这些方法可以加快编码的速度。当我写脚本的时候,我总是使用这些方法。而且我可以很肯定的说,它们帮我节约了不少时间。

6、经常使用内部命令

无论碰到哪种情况,请尽量考虑使用内部命令而不是外部命令。在此前的一篇题为《内部命令和外部命令》的文章里,我们可以看到二者间的差异。用内部命令对你永远都有好处。根据正在处理的输入文件的大小,内部命令可以在性能方面为你节省很多。虽然你并不总是有这样选择内部命令抑或外部命令的机会,但在某些情况下,你一定能做出正确的选择。

7、没有必要使用cat命令

这是我们经常在论坛里讨论的话题之一。没有必要使用cat命令指的是在有些时候,我们会发现根本没有必要使用cat命令。有时候,使用了多余的cat命令会让你的代码看起来很丑陋,而且还会带来性能上的问题。

例如:
代码
$ cat /etc/passwd | grep guru

正确的方法应该是:
代码
$ grep guru /etc/passwd

8、仔细阅读错误信息

程序员常犯的一个错误是:当我们敲入的命令报错后,我们中的大多数人只是对错误信息一瞥而过,而不会去认真的读一读。很多时候,错误信息里就包含了解决办法。更重要的是,有时候我们修改了某个错误并再次运行后,系统依旧会报错。然后我们再次修改,但系统再次报错。这可能会持续很长时间。但实际上,旧的错误可能已经被纠正,只是由于出现了其它一些新错误才导致系统再次报错。而我们依旧在怀疑为什么修改好的代码依然不能正常运行。因此,请你养成仔细阅读错误信息的习惯。

9、尽量避免臃肿的命令

你正在尝试去从一个大的文件中筛选某条信息。接下来你可能写一大堆命令来实现这一功能。可是,尽管你将得到正确的结果,你写的命令却不够好,且晦涩难懂。因此,我们应该尽量避免这种情况发生。下面这个例子就是代码优化的好例子。

例如:检索用户ID值为502的用户名。

下面的命令不好:
代码
$ grep 502 /etc/passwd | cut -d: -f1

这条命令也不够好:
代码
$ grep 502 /etc/passwd | awk -F”:” ‘{print $1}’

这才是一条好的命令:
代码
$ awk -F”:” ‘$3==502{print $1}’ /etc/passwd

正如以上示例,用一条简单的awk命令就可以完成检索任务。

10、别吝啬添加注释

你写了一份脚本。一两个星期后,你再次打开脚本文件,如果没有注释在里面的话,你可能会花上很多时间才能理解这些代码。虽然代码是我们自己写的,但这依旧会浪费我们很多的时间。脚本是用来节省时间的,因此,我们没有理由浪费时间去理解这些用来节省时间的文件。所以,请养成在脚本中添加注释的好习惯。这些注释不必很详细,能让自己或别人读懂就行。

Posted 2012年04月3日 by gw8310 in linux

Calling Salesforce Web Services Using Apex   Leave a comment

http://developer.force.com/cookbook/recipe/calling-salesforce-web-services-using-apex

 

Problem

Most, if not all, of the Web service examples and tutorials use an external programming language to call/invoke the salesforce Web services. However, this requires external hardware and software to run and is not native to the salesforce platform. With a few tweaks to the salesforce Web services’ wsdl and Apex generated classes, it’s possible to invoke them through native Apex.

Solution

To begin, you always need to have either an Apex Partner or Enterprise Web service class so that you can login and get a session id, which will be used in any future Web service calls.

Let’s generate an Apex Partner Web service class first.

  1. Go to Setup | Develop | API -> Click on “Generate Partner WSDL”.
  2. Save the file and name it “Partner.wsdl”.
  3. Go to Setup | Develop | Apex Classes -> Click on “Generate from WSDL”.
  4. Select the “Partner.wsdl” file and click the “Parse” button.
  5. Accept the default class names and click the “Generate Apex code” button.
  6. Now, you’ll see the following message “The following generated class(es) have compilation errors: Error: partnerSoapSforceCom Error: unexpected token: ‘delete’ at 670:51”. This results from some of the partner web methods being the same as Apex DML keywords. To resolve this, simply change the name of the Apex method names.
  7. Copy all the partnerSoapSforceCom Apex code in the textbox.
  8. Go to Setup | Develop | Apex Classes -> New.
  9. Paste the partnetSoapSforceCom Apex code.
  10. Change
    1 public partnerSoapSforceCom.DeleteResult[] delete(String[] ids)

    to

    1 public partnerSoapSforceCom.DeleteResult[] deleteSObjects(String[] ids)
  11. Change
    1 public partnerSoapSforceCom.UpsertResult[] upsert

    to

    1 public partnerSoapSforceCom.UpsertResult[] upsertSObjects
  12. Change
    1 public partnerSoapSforceCom.MergeResult[] merge

    to

    1 public partnerSoapSforceCom.MergeResult[] mergeSObjects
  13. Change
    1 public partnerSoapSforceCom.SaveResult[] update

    to

    1 public partnerSoapSforceCom.SaveResult[] updateSObjects
  14. Change
    1 public partnerSoapSforceCom.UndeleteResult[] undelete

    to

    1 public partnerSoapSforceCom.UndeleteResult[] undeleteSObjects

Now you have an Apex Partner class.

 

Next, let’s generate an Apex class for the Apex Web service.

  1. Go to Setup | Develop | API -> click the “Generate Apex WSDL” button.
  2. Save the file as “Apex.wsdl”.
  3. Go to Setup | Develop | Apex Classes -> Click on “Generate from WSDL”.
  4. Select the “Apex.wsdl” file and click the “Parse” button.
  5. Keep the default “soapSforceCom200608Apex” name and click the “Generate Apex code” button.

Now, you should see the following message “The following generated class(es) compiled successfully with no errors: soapSforceCom200608Apex”, which indicates that you now have an Apex class for the Apex Web service.

 

Before we can use some code to demonstrate that this works, we have to configure our org so that we’re allowed to call the Web services. Not a biggie.

  1. Go to Setup | Security Controls | Remote Site Settings
  2. Click “New Remote Site”.
  3. Enter “SalesforceLogin” for the Site Name.
  4. Enter either “https://login.salesforce.com&#8221; or “https://test.salesforce.com&#8221; as the Remote Site URL depending on your org.
  5. Click Save. Now, you have granted your org the ability to login, but you still have to grant it access to the correct salesforce web node to allow the Apex Web service to be called, which we’ll do next.
  6. Go to Setup | Security Controls | Remote Site Settings
  7. Click “New Remote Site”.
  8. Enter “SalesforceApex” for the Site Name.
  9. Enter “https://<Prefix>-api.salesforce.com&#8221; where <Prefix> is the salesforce sub-domain you’re using, which can be found by looking at the URL in your browser. Since I’m on “https://na12-api.salesforce.com&#8221;, I would enter “https://na12-api.salesforce.com&#8221;.
  10. Click “Save”

Now, we’re ready to run a quick example that will run all the unit tests in our org in a synchronous fashion.

 

01 partnerSoapSforceCom.Soap sp = new partnerSoapSforceCom.Soap();
02
03 /* For demonstration purposes only, enter your credentials on the following
04    lines, but if you're going to use this a lot or in production, encrypt your credentials and store them somewhere and then decrypt them here.
05 */
06 String username = '<Your username here>';
07 String password = '<Your password here>';
08
09 partnerSoapSforceCom.LoginResult loginResult = sp.login(username, password);
10
11 system.debug('   loginResult ' + loginResult);
12
13 soapSforceCom200608Apex.Apex apexWebSvc = new soapSforceCom200608Apex.Apex();
14 soapSforceCom200608Apex.SessionHeader_element sessionHeader = new soapSforceCom200608Apex.SessionHeader_element();
15 sessionHeader.sessionId = loginResult.sessionId;
16
17 // The Web services have a maximum timeout of 2 minutes. The timeout value
18 // is in milliseconds.
19 apexWebSvc.timeout_x = 120000;
20 apexWebSvc.SessionHeader = sessionHeader;
21
22 soapSforceCom200608Apex.RunTestsRequest testsRequest = new soapSforceCom200608Apex.RunTestsRequest();
23 testsRequest.allTests = true;
24         
25 soapSforceCom200608Apex.RunTestsResult testResults = apexWebSvc.runTests(testsRequest);
26
27 /* Do something worthwhile with the test results here */

Discussion

This is just the tip of the iceberg, since we’re only using the Apex Web service. With a little bit of effort, you can generate an Apex Metadata class for the Metadata Web service. This could “theoretically”, for example, let you deploy code from one org to another using a “deployment” org without the need of the migration tool.

Another example would be creating an automated testing scheduled job, using the above code as a starting point, and emailing the results to your development team. Keep in mind that if you have a lot of tests, it may take longer than 120 seconds and this approach won’t work. You’ll have to switch to the asynchronous “ApexTestQueueItem” and “ApexTestResult” objects, but they don’t currently provide nearly as much information as the synchronous “RunTestsResult” object.

From here, try out different things and please share your findings. I’m certain I’m not the only interested party.

I hope this helps and happy coding.

Luke

Posted 2012年03月8日 by gw8310 in salesforce

salesforce and paypal   Leave a comment

http://techsahre.blogspot.com.au/2011/01/simple-paypal-integration-with.html

Hi All,
Recently I got a need to implement Paypal integration with Salesforce for a basic payment for Merchant Type account, the payments would be from Customers using Credit Cards like Visa etc. I started looking into Paypal methods to find out which is best to implement using Apex, then i found one old blog post very helpful (Unfortunately that blog post is removed recently so not able to paste url here). The method which i preferred is DoDirectPayment. I did some modification in that code and provided in this blog.
The main problem i faced, was not the code, the testing. Like me, many new developers face this problem, thats why i came with this blog to describe step by step procedure to do a simple test with your paypal payment process using salesforce code. This might be useful for the developers who dealing with Paypal first time as well as want to integrate it with Salesforce.

1) Setup one sandbox account.

Go to http://developer.paypal.com and create one account there. After creating, login there only. In the left menu you will find “Test Accounts” link. Click on that.
From the right side screen, you can create multiple test accounts.
For testing purpose generally you need two type of accounts. One is “Seller” and one is “Buyer”. Its always better to create preconfigured accounts.
Click on “PreConfigured” link to create one ‘Buyer’ account, set some amount there.
Click on “PreConfigured” link to create one ‘Seller’ account, set some amount there.
Click on “PreConfigured” link to create one ‘Website Payments Pro’ account, used for Merchant (Seller), set some amount there. Dont choose seller account this time because we going to use “DoDirectPayment” API method which need this type of account.

We dont need “Seller” account but i found after some struggle that if you not create any Seller account first then if you create any ‘Website Payments Pro’, then it will always be “unverified”. I am not sure why it is like this. But this is “My Best Practice” that you should first create one Seller account, then create this ”Website Payments Pro’ account. And verify, that one is marked as “Verified” as shown in the below screenshot.

2) Test Merchant Account API Setup

Now, select your ‘website payments pro’ account using radio button there and click ‘Enter Sandbox Test Site’.
Login with your password.
Click on Profile link after you login. It will be on top right side.
Click on ‘Request API Credentials’ link in bottom left side.
Click on ‘Set up PayPal API credentials and permissions’ link.
Click on ‘View API Signature’ link and note down your API Username, API Password, API Signature
Click on ‘Grant API Access’ link on previous screen. Here give your API username and Check all checkboxes and Save
Now you ok with configuration.

2) Salesforce Code setup
Now copy paste following Apex Class code in your org.
Add “https://api-3t.sandbox.paypal.com/2.0/&#8221; url into “Remote Site Setting”.

In the below code change your API Username, API Password and Signature.

3) Run and Test
Now you can use below code to do a sample payment. Run this code either on your VF screen or from System Log screen.

You will see that you got one Transaction Id and ‘Success’ message. If you dont find success message, then print “err” property to check whats wrong.
Log into your test pro account and check your balance, it might be increased. If so, its all fine 🙂

Thanks
Aslam Bari

Posted 2012年03月7日 by gw8310 in salesforce