Sky's blog

          我和我追逐的夢

          常用鏈接

          統(tǒng)計

          其他鏈接

          友情鏈接

          最新評論

          使用雙重解析器的descriptor屬性來嚴(yán)格約束依賴解析

                  在討論這個問題前,先簡單的介紹一下雙重解析器的工作原理:顧名思義,雙重解析是雙重的:它由一個ivyResolver和一個artifactResolver組成,其中ivyResolver負(fù)責(zé)解析ivy的模塊描述符,而artifactResolver則用于解析制品。換言之,ivyResolver用來指明需要什么,而artifactResolver則負(fù)責(zé)獲取具體的制品文件。

              舉例說,下面的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,指向本地文件系統(tǒng),這里有我們需要使用的依賴的模塊描述符。public-ibiblio作為artifactResolver,實際是指向一個基于nexus的本地maven 倉庫(maven術(shù)語叫做企業(yè)倉庫,類似私服的概念,proxy + cache),所有的制品比如最常見的jar包都是從這里獲取的。

              個人感覺ivy設(shè)計使用dual resolver的初衷是:通過控制ivyResolver的內(nèi)容來達(dá)到控制整個系統(tǒng)中所有第三方依賴,即只使用ivyResolver中提供好的依賴(包括版本)。比如說只使用spring2.5.6版本,不容許不同開發(fā)人員和不同的project使用spring的其他版本,再比如都使用easymock,不容許個別人因為個人喜好而是用jmock......同時有利于日后的版本維護(hù)和版本升級,方便解決版本沖突。

              開發(fā)過大型java系統(tǒng)的朋友應(yīng)該都會遇到上面的這些問題,比如我曾經(jīng)參與的產(chǎn)品,有超過200個的java project,無數(shù)依賴,管理起來非常痛苦。   

              第一次在學(xué)習(xí)ivy的過程中看到ivy中的雙重解析器,就感覺設(shè)計非常的不錯,可以比較好的解決這方面的問題。只要維護(hù)好ivyResolver中的依賴,則整個系統(tǒng)中的依賴都被限制在這個范圍中。比如如果有人想用spring2.5.6之外的版本,哼哼,ivyResolver解析器會不工作的......

              但是,在實際的使用過程中發(fā)現(xiàn),雙重解析器的工作模式有點問題:如果目標(biāo)依賴在ivyResolver中可以找到則情況正常,但是如果目標(biāo)依賴在ivyResolver中沒有定義,ivy居然會在artifactResolver的繼續(xù)查找!然后報告說依賴解析成功已下載云云,而不是我期望的無法解析,暈倒。如果是這樣的話完全達(dá)不到預(yù)期的目標(biāo)嘛。

          [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的文檔,結(jié)果一無所獲,基本沒有任何相關(guān)的說明,參考文檔中dual resolver根本沒有任何屬性可以用來設(shè)置上述約束。上google大法,無果,暈,我到底要怎么樣做才能讓這中解析失敗呢?

              中午吃了個飯回來,恩,中間因為想這個事情走神被同事誤解為感冒了身體不好......想想還有最后一招,反正手頭有源代碼,萬一真不行我改改總可以吧?打開org.apache.ivy.plugins.resolver.DualResolver,意外發(fā)現(xiàn)有這么一段:

              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應(yīng)該是optional module descriptor。如果容許可選的模塊描述符,則ivy會在ivyResolver查找不到的情況下使用artifactResolver來繼續(xù)解析。這個屬性的相關(guān)設(shè)置代碼如下:


              
          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

              問題解決,雙重解析器現(xiàn)在和預(yù)期的一樣工作。

              小小的抱怨一下,ivy的文檔雖然在開源項目中已經(jīng)算很不錯了,但是在這些小的細(xì)節(jié)上還是有疏漏,比如這里的descriptor屬性,如果沒有它雙重解析器基本上是無法達(dá)到設(shè)計目標(biāo)的。看來多翻翻源代碼是有必要的^0^

          posted on 2009-11-04 13:40 sky ao 閱讀(1757) 評論(0)  編輯  收藏 所屬分類: project building

          主站蜘蛛池模板: 大丰市| 广东省| 汝城县| 澳门| 西乡县| 花莲市| 裕民县| 定兴县| 荆州市| 正蓝旗| 保康县| 买车| 明光市| 潍坊市| 富平县| 克山县| 惠来县| 宝清县| 台东县| 拜城县| 中西区| 介休市| 秀山| 洱源县| 巍山| 崇仁县| 宝山区| 额尔古纳市| 巴楚县| 安阳市| 玉环县| 北票市| 高雄县| 太仆寺旗| 任丘市| 潜江市| 河北区| 咸丰县| 潮安县| 定结县| 密山市|