高老庄

八戒的梦想:农妇,山泉,有点田
posts - 4, comments - 14, trackbacks - 0, articles - 3
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2009年11月1日

 Architexa的前身是relo,这个工具在分析开源项目的源码时很好用,relo已经不再维护,变成了新的插件Architexa,其网址是http://www.architexa.com/,虽然说architexa东西不错,可惜需要付费.另外他的注册网站好像有问题,因此连评估也做不了,无奈之下,动了暴力破解的念头.下面即是暴力破解的过程,需要的人可以参考下.
1.architexa 通过eclipse的update manager 下载后,在eclipse_HOME/plugins会存在几个jar和目录,如下:


1.architexa 没有对编译后的代码混淆,先用java decompiler 反编译出如下的类:
  • com.architexa.diagrams.RSECore 位于com.architexa.diagrams_1.2.2.201006051418.jar中.
  • com.architexa.rse.ConnectAccountDialog 位于com.architexa.intro_1.2.2.201006051418/ReloIntro.jar中
2.修改RSECore类的方法:
 1 public static boolean validInstall()
 2 {
 3     if (!AccountStatusUtils.testAccountValid()) {
 4       String email = AccountSettings.getStoredAccountEmail();
 5       AccountSettings.getStoredAccountPassword();
 6       if ((email != null&& (email.length() > 0))
 7         AccountErrorMsgs.displayErr("Account Has Expired ");
 8       return false;
 9     }
10     return true;
11 }
12
中间的判断可以完全拿掉,修改为如下即可:
1 public static boolean validInstall()
2 {
3     return true;
4 }

3.修改ConnectAccountDialog类的代码(反编译后的代码有点长,这里不列出了),最终改成如下即可:
1 protected void okPressed_Internal() {
2     this.emailEntered = this.emailField.getText();
3     this.passwordEntered = this.passwordField.getText();
4 
5     AccountConnection ac = new AccountConnection();
6     if (this.enableOnOK) ac.setMenuToDisable(!this.disableOnCancel);
7     super.okPressed();
8 }

编译后将上述两个类放到对应的jar中,重启eclipse.

4.在architexa的认证对话框,输入任意email和password,architexa 将重建索引.
5.在某个java类的上下文菜单中,可以看到Open in Diagram 就可以生成类的布局图,类图和序列图了.可以通过工具栏上的button来输出图形.

下面贴几个通过这个插件构成的图,欣赏下





posted @ 2010-06-15 17:34 高老庄 阅读(3393) | 评论 (14)编辑 收藏

    hudson是开源社区用的较多的一个开源持续集成工具,因为其开源,使用方便,扩展性强,对既有构建系统耦合性低,受到了大家一致的好评.
    使用:
    1.下载 
        hudson的官方网站https://hudson.dev.java.net/下提供了下载
    2.安装
        hudson以war包的方式提供,因此安装方式极其简单,直接放到服务器的相应目录下,这里放到tomcat的webapp下,启动后,访问http://localhost:8088/hudson 可以进入hudson的控制台页面.
      
    4.组织待构建的项目
        这里我们创建一个最为简单的任务.这个任务的目的是构建一个标准的java工程,将其中的源码编译,打包等.
        回顾下一般的、最为简单的开发流程:开发人员开发代码,然后利用诸如ant,mvn等负责构建系统,然后执行测试,最后发布到服务器上.通常,每个项目都会有一个完整的脚本来自动化的做这件事,如何驱动自动化脚本的执行(什么时间点,以什么频率,管理构建结果),是hudson提供给我们的功能,hudson不关注特定一次构建的内部过程,这对hudson是透明的.目前,hudson通过插件的方式,提供了对基于ant 、mvn等常见构建工具的支持.本质上,hudson是一个任务管理和驱动执行工具,只不过,它驱动的软件开发流程中的构建等过程.
        准备:解决我们特定一次构建中,做什么的问题.
        基于测试的目的,我们创建一个示例java工程,结构如下:
    
    此项目的采用ant,构建,ant脚本如下:
    
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." name="build.hudsondemo">
    
<!-- ================================= 
          target: compile              
         ================================= 
-->
    
<target name="compile" depends="prepare" description="compile the project to the bin">
        
<javac debug="true" destdir="${basedir}/bin">
            
<src path="${basedir}/src" />
            
<src path="${basedir}/test"  />
            
<classpath>
                
<fileset dir="${basedir}/lib">
                    
<include name="*.jar"/>    
                
</fileset>
            
</classpath>
        
</javac>
    
</target>
    
    
<!-- ================================= 
          target: jar              
         ================================= 
-->
    
<target name="jar" depends="compile" description="jar the project">
        
<mkdir dir="${basedir}/target"/>
        
<jar  destfile="${basedir}/target/hudsondemo_${common.version}.jar">
            
<fileset dir="${basedir}/bin" />
        
</jar>
    
</target>
    
    
<!-- ================================= 
          target: prepare              
         ================================= 
-->
    
<target name="prepare" depends="clean"  description="prepare the jar to the lib">
        
<copy todir="${basedir}/lib">
            
<fileset dir="${common.libs.dir}">
                
<include name="*.jar"/>
            
</fileset>
        
</copy>
    
</target>
    
    
<!-- ================================= 
              target: prepare              
             ================================= 
-->
    
<target name="clean">
        
<delete dir="${basedir}/bin"></delete>
        
<delete dir="${basedir}/lib"></delete>
        
        
<mkdir dir="${basedir}/bin" />
        
<mkdir dir="${basedir}/lib" />
    
</target>
</project>

    为了说明问题,我特意的设定两个构建时参数:
    common.libs.dir 指出从什么位置获取编译项目所需要的jar
    common.version 指出构建的jar的版本号.

    5.配置hudson的通用配置
        根据使用插件的多少,通用配置数量同,对上述的示例项目,我们需要配置 ant 和jdk(可选,如果需要指定用特定的jdk构建系统的话).
        点击hudson主页面右上角的manger hudson,进入配置页面,有多项配置可以处理,但是目前仅仅需要用到System configurate 功能.在System configurate页面,可以如下的配置:

    
    贴此图的目的是需要关注下home directory这个配置,默认是当前用户目录下的.hudson,可以更改,一般在环境变量中设定一个HUSDON_HOME即可,同时将原有目录下文件copy到新目录下,重启hudson即可.也可以用其他的方式,比如设定容器参数等来指定.
    上述配置取默认既可.
    
    配置jdk:
    
    
    配置ant:
    
    
     
   6. 创建构建任务
        hudson能提供的功能都以任务存在.点击右上角的new job,将构建一个新的任务:
    
    输入任务名称,并选择第二项.

    配置任务:解决如何安排构建任务的执行的问题.
    首先,我们需要指定如何保留构建历史,一种是基于时间的,保留多少天,一种是基于次数的,保留自当前开始多少次以内的.这里我们选择保留最新3次构建.
    
    再次,我们需要指定利用什么版本ant执行构建,同时指定构建时参数.
    
    ant version 版本中,使用了在通用配置部分配置的ant.
    targets 中,指明了,每次构建时需要完成的target,可以指定多个target.
    build file 指明了,使用什么样的ant完成实际的构建过程.
    properties 指明了ant脚本中的使用的运行时参数.这些参数可以使用变量替换,hudson 会解析出实际的值再传给ant.

    这就是这个任务可以执行的最基本配置,保存,并点击右上角的build new ,可以立即执行一个构建.构建结果如下:
    
    红色表示失败构建,如果失败,可以在%HUDSON_HOME%\jobs\下查看对应任务构建的日志来排查问题.
    
    8. 两个可能经常需要关注的配置.
    1.每个job的 workspace.
        
        如果不指定绝对路径,配置的ant等脚本就是相对这个工作空间的.在上面的例子中工作空间的用处不大,但是在一些其他类型的构建,比如从svn中签出代码构建时,用处就体现出来了,另外,一些hudson的插件,所利用的文件(构建脚本生成,这些插件不会去关注文件产生,而是对这些文件做二次处理)都是放到工作空间的,工作空间相当与构建系统和hudson的一个交流中介.推荐是每个项目有自己独立的工作空间.
    2.自动构建的频率设定
    
    也就是什么时候触发构建,三种方式:
        当别的项目构建完毕后发生构建
        利用cron表到式来指定频率,对cron表达式不熟悉的话,可以参考quartz(hudson内部使用的调度框架)相关的文档.
        检测scm(svn、cvs等)的状态,如果检测到变化,自动发生构建.

    借助husdon,基本能做到无人值守构建和部署,不少插件可以利用,也可以开发自己的插件.上面的仅仅是一个例子而与,如果要应对实际工作中的问题,得好好研究才行.
    

posted @ 2010-01-25 18:58 高老庄 阅读(749) | 评论 (0)编辑 收藏

    在使用osgi实现时,可以使用诸如install,start,stop这样的命令来管理bundle或者调用服务.有时我们可能想添加一些自定义命令.可以通过如下的步骤来实现
    1.编写一个服务,实现如下的接口

1public interface CommandProvider {
2    /**
3     Answer a string (may be as many lines as you like) with help
4     texts that explain the command.
5     */

6    public String getHelp();
7
8}


如果想定义hello方法,可以如下实现该接口:

 

import java.util.Dictionary;
import java.util.Properties;

import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
public class Activator implements BundleActivator,CommandProvider  {
    BundleContext bundleContext
=null;
    
public void start(BundleContext context) throws Exception {
        System.out.println(
"start" +context.getBundle().getLocation());
        bundleContext
=context;
        context.registerService(CommandProvider.
class.getName(), new AntherCommandProvider(), null);
        Dictionary dictionary
=new Properties();
        dictionary.put(Constants.SERVICE_RANKING, 
10);
        context.registerService(CommandProvider.
class.getName(), this,dictionary);
        
    }


    
public void stop(BundleContext context) throws Exception {
        System.out.println(
"end" +context.getBundle().getLocation());
    }


    
public String getHelp() {
        
return "you are using the help command";
    }

    
    
public void _helloa(CommandInterpreter intp)
    
{
        intp.println(
"helloa "+ this.getClass().getName());
    }

    
    
public void _hello(CommandInterpreter intp) throws Exception {
        intp.println(
"hello " + this.getClass().getName());
    }

}


 

import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;

public class AntherCommandProvider implements CommandProvider {

    
public void _hello(CommandInterpreter intp)
    
{
        intp.println(
"hello "+ this.getClass().getName());
    }

    
public String getHelp() {
        
return null;
    }

}


其中,通过CommandInterpreter类型的nextArgument()方法可以迭代出所有的命令参数.
    2.注册服务
        如果不将该接口注册为服务,这个hello命令将不产生任何作用.注册的服务名称必须是org.eclipse.osgi.framework.console.CommandProvider.
       当系统中存在多个此接口的实现时,可以通过SERVICE_RANKING属性来决定了命令执行的顺序,既有最高值的服务将被优先执行.这种方式可以重载系统中已经存在的同名服务.
     3.执行命令
    请仔细体会输出结果

posted @ 2010-01-22 17:34 高老庄 阅读(595) | 评论 (0)编辑 收藏

先谈下这个解决方案的背景:
    假设一个公司的产品遵循的是先有基础平台,然后在此平台上构建不同的产品,最后每一个产品被实施到特定的项目,那么,他们就构成了一种层次化的结构.每一个层次,需要覆盖一些上一层次的配置或者创建新的配置,如何分割层次间的影响从而保证层次间的独立性,是一个挑战.
    任意层次,可能有多个模块或者组件构成,不同的组件间,配置的类型可能一样,但是配置的数据不一样,那么,如果在配置某个模块时,不比考虑其他模块的配置情况,那么这个模块就拥有开发时的独立性,当组件被集成到同一层次部署运行时,配置的合并和重组是一个问题,并且,组件间可能存在依赖关系,这种依赖关系同时产生了依赖组件间配置加载的优先级问题.
    成熟的软件,一般不会直接将第三方的软件集成,而是将其封装后在纳入进来,第三方组件的配置往往不具备配置的层次化或者模块独立性.在设计第三方组件的集成策略时,需要考虑使其拥有上述两种能力.
    解决上述问题,方式有很多种,我们谈论比较容易实现的一种.
    这种解决方案的基本思路如下:
    首先,设计一个特定的扩展名称的配置文件(模块配置索引文件,MCIF,xml格式),此配置文件面向的是组件级别,即每个组件定义自己的MCIF.MCIF中定义若干配置类别,即名称空间,每一个名称空间负责完成一类配置,一般,一个名称空间对应一个配置获取接口.这个名称空间中仅仅配置所关注的配置的文件的相对位置(相对此MCIF),这样,最大化的减少了不同配置文件格式对MCIF的影响.
    每一个MCIF的根元素拥有一个parent属性,指向了上一层次,同一层次的MCIF的parent属性都相同.通过parent属性,配置的层次化就不是问题了.
    MCIF有两个特殊的名称空间:
    1.register 定义了所支持的名称空间及其对应的配置解析器,这样,此配置框架就可以允许对名称空间进行扩展.
    2.depends 定义了同一层次的模块间的依赖关系,这个是可选的,如果没有实现或者配置,同一层次的module即为平行的.
    
    当系统启动时,扫描所有的MCIF,并根据parent属性解析出一个层次关系,对每一个层次下module,参考相应的depends设置定义出一个依赖关系.
    当请求某特定的配置时,根据上述的两个关系完成配置的组合,并返回给使用者.
    
    公司最近的重构中,基于这个思想开发的配置小框架,很好完成了多层次,多组件的配置覆盖问题,配置相对以前更清晰、简单,配置过程中的关注点大大减少.

posted @ 2009-11-04 15:45 高老庄 阅读(208) | 评论 (0)编辑 收藏

        工作三年有余,接触的东西零碎不堪,私下研究不少,可惜工作中很少使用,随着时间的久远而逐渐忘却,一直有个想法,能讲所学所思整理出来,以便日后参考查阅.
        长久以来,看别人的blog不少,虽然有深度的原创不多,确也给了我莫大的帮助,本着取于斯,回馈于斯的精神,决定也在网上选择一片信手涂鸦之地.几经斟酌,最终敲定了blogjava,希望能将这个blog坚持下去,见证一个尘世迷途小卒的成长历程.
         希望不至于虎头蛇尾,that't all!
        
       

posted @ 2009-11-01 11:13 高老庄 阅读(146) | 评论 (0)编辑 收藏