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 閱讀(1767) 評論(0)  編輯  收藏 所屬分類: project building

          主站蜘蛛池模板: 道真| 朝阳县| 朝阳市| 慈利县| 文昌市| 文登市| 盘锦市| 阆中市| 临夏县| 宜都市| 新密市| 黄石市| 加查县| 拜城县| 搜索| 荃湾区| 榆中县| 临潭县| 民权县| 安福县| 土默特右旗| 黑河市| 含山县| 上虞市| 佛教| 珠海市| 马边| 怀化市| 赞皇县| 仙居县| 前郭尔| 镇雄县| 赤峰市| 固始县| 西乡县| 文山县| 大洼县| 丹阳市| 信丰县| 溧水县| 界首市|