Sky's blog

我和我追逐的梦

常用链接

统计

其他链接

友情链接

最新评论

使用双重解析器的descriptor属性来严格约束依赖解析

        在讨论这个问题前,先简单的介绍一下双重解析器的工作原理:顾名思义,双重解析是双重的:它由一个ivyResolver和一个artifactResolver组成,其中ivyResolver负责解析ivy的模块描述符,而artifactResolver则用于解析制品。换言之,ivyResolver用来指明需要什么,而artifactResolver则负责获取具体的制品文件。

    举例说,下面的ivy配置:
<ivysettings>
    
<properties file="ivysettings-public.properties" />
    
<settings defaultResolver="public" />
    
<resolvers>
        
<dual name="public" descriptor="required">
            
<filesystem name="public-ivy">
                
<ivy pattern="${path.public.depository.dir}/[organisation]/[module]/ivy-[revision].xml" />
            
</filesystem>
            
<ibiblio name="public-ibiblio" m2compatible="true"
                root
="http://192.168.0.30:8081/nexus/content/groups/public/"
                pattern
="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
                usepoms
="false" >
                
</ibiblio>
        
</dual>
    
</resolvers>
</ivysettings>

    其中的public-ivy作为ivyResolver,指向本地文件系统,这里有我们需要使用的依赖的模块描述符。public-ibiblio作为artifactResolver,实际是指向一个基于nexus的本地maven 仓库(maven术语叫做企业仓库,类似私服的概念,proxy + cache),所有的制品比如最常见的jar包都是从这里获取的。

    个人感觉ivy设计使用dual resolver的初衷是:通过控制ivyResolver的内容来达到控制整个系统中所有第三方依赖,即只使用ivyResolver中提供好的依赖(包括版本)。比如说只使用spring2.5.6版本,不容许不同开发人员和不同的project使用spring的其他版本,再比如都使用easymock,不容许个别人因为个人喜好而是用jmock......同时有利于日后的版本维护和版本升级,方便解决版本冲突。

    开发过大型java系统的朋友应该都会遇到上面的这些问题,比如我曾经参与的产品,有超过200个的java project,无数依赖,管理起来非常痛苦。   

    第一次在学习ivy的过程中看到ivy中的双重解析器,就感觉设计非常的不错,可以比较好的解决这方面的问题。只要维护好ivyResolver中的依赖,则整个系统中的依赖都被限制在这个范围中。比如如果有人想用spring2.5.6之外的版本,哼哼,ivyResolver解析器会不工作的......

    但是,在实际的使用过程中发现,双重解析器的工作模式有点问题:如果目标依赖在ivyResolver中可以找到则情况正常,但是如果目标依赖在ivyResolver中没有定义,ivy居然会在artifactResolver的继续查找!然后报告说依赖解析成功已下载云云,而不是我期望的无法解析,晕倒。如果是这样的话完全达不到预期的目标嘛。

[ivy:resolve] :: resolving dependencies :: net.runafter.skymaildemo#Pop3Resource;working@EV001A4B84D85E
[ivy:resolve]     confs: [default, master, compile, runtime, test]
[ivy:resolve]     found commons-lang#commons-lang;2.4 in public-ibiblio
[ivy:resolve] :: resolution report :: resolve 218ms :: artifacts dl 0ms

    郁闷中开始翻dual resolver的文档,结果一无所获,基本没有任何相关的说明,参考文档中dual resolver根本没有任何属性可以用来设置上述约束。上google大法,无果,晕,我到底要怎么样做才能让这中解析失败呢?

    中午吃了个饭回来,恩,中间因为想这个事情走神被同事误解为感冒了身体不好......想想还有最后一招,反正手头有源代码,万一真不行我改改总可以吧?打开org.apache.ivy.plugins.resolver.DualResolver,意外发现有这么一段:

    public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data)
            
throws ParseException {
        
if (ivyResolver == null || artifactResolver == null) {
            
throw new IllegalStateException(
                    
"exactly two resolvers must be added: ivy(1) and artifact(2) one");
        }
        ResolvedModuleRevision resolved 
= data.getCurrentResolvedModuleRevision();
       
        data 
= new ResolveData(data, doValidate(data));
        
final ResolvedModuleRevision mr = ivyResolver.getDependency(dd, data);
        
if (mr == null) {
            checkInterrupted();
            
if (isAllownomd()) {
                Message.verbose(
"ivy resolver didn't find " + dd
                        
+ ": trying with artifact resolver");
                
return artifactResolver.getDependency(dd, data);
            } 
else {
                
return null;
            }
        } 
else {
            
if (mr == resolved) {
                
// nothing has actually been resolved here, we don't need to touch the returned rmr
                return mr;
            }
            
return new ResolvedModuleRevision(
                mr.getResolver(), 
this, mr.getDescriptor(), mr.getReport(), mr.isForce());
        }
    }

    OK,就是这个了,allownomd属性看来就是用来干这个的,omd应该是optional module descriptor。如果容许可选的模块描述符,则ivy会在ivyResolver查找不到的情况下使用artifactResolver来继续解析。这个属性的相关设置代码如下:


    
public static final String DESCRIPTOR_OPTIONAL = "optional";
    
public static final String DESCRIPTOR_REQUIRED = "required";

private boolean allownomd = true;

public boolean isAllownomd() {
        
return allownomd;
    }

    
public void setAllownomd(boolean allownomd) {
        Message.deprecated(
            
"allownomd is deprecated, please use descriptor=\""
            + (allownomd ? DESCRIPTOR_OPTIONAL : DESCRIPTOR_REQUIRED) + "\" instead");
        this.allownomd = allownomd;
    }

    
/**
     * Sets the module descriptor presence rule.
     * Should be one of {
@link #DESCRIPTOR_REQUIRED} or {@link #DESCRIPTOR_OPTIONAL}.
     * 
     * 
@param descriptorRule the descriptor rule to use with this resolver.
     
*/
    
public void setDescriptor(String descriptorRule) {
        
if (DESCRIPTOR_REQUIRED.equals(descriptorRule)) {
          allownomd 
= false
        } 
else if (DESCRIPTOR_OPTIONAL.equals(descriptorRule)) {
          allownomd 
= true
        } 
else {
            
throw new IllegalArgumentException(
                
"unknown descriptor rule '" + descriptorRule
                
+ "'. Allowed rules are: "
                
+ Arrays.asList(new String[] {DESCRIPTOR_REQUIRED, DESCRIPTOR_OPTIONAL}));
        }
    }

    试着在ivy配置文件的dual上加上descriptor属性
    <dual name="public" descriptor="required">

    再试就ok了:


[ivy:resolve]
[ivy:resolve] :: problems summary ::
[ivy:resolve] :::: WARNINGS
[ivy:resolve]         module not found: commons-lang#commons-lang;2.4
[ivy:resolve]     ==== public-ivy: tried
[ivy:resolve]       C:/aoxj/workspace/peasonal/study/java/tools/ivy/skyMailDemo/skyMail/ivy/depositories/public/commons-lang/commons-lang/ivy-2.4.xml
[ivy:resolve]     ==== public-ibiblio: tried
[ivy:resolve]         ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve]         ::          UNRESOLVED DEPENDENCIES         ::
[ivy:resolve]         ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve]         :: commons-lang#commons-lang;2.4: not found
[ivy:resolve]         ::::::::::::::::::::::::::::::::::::::::::::::
[ivy:resolve]
[ivy:resolve]
[ivy:resolve] :: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS

    问题解决,双重解析器现在和预期的一样工作。

    小小的抱怨一下,ivy的文档虽然在开源项目中已经算很不错了,但是在这些小的细节上还是有疏漏,比如这里的descriptor属性,如果没有它双重解析器基本上是无法达到设计目标的。看来多翻翻源代码是有必要的^0^

posted on 2009-11-04 13:40 sky ao 阅读(1740) 评论(0)  编辑  收藏 所属分类: project building


只有注册用户登录后才能发表评论。


网站导航: