注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Nutch 1.0 源代码分析[3] Plugin(2)   

2010-03-21 12:59:55|  分类: Nutch |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

         URLNormalizers构造函数中,有一句没有看:

this.extensionPoint = PluginRepository.get(conf).getExtensionPoint(

       URLNormalizer.X_POINT_ID);

         看一下PluginRepository.get函数:

public static synchronized PluginRepository get(Configuration conf) {

    PluginRepository result = CACHE.get(conf);

    if (result == null) {

       result = new PluginRepository(conf);

       CACHE.put(conf, result);

    }

    return result;

}

         先试着从CACHE取,如果没有被缓存过,那么就调用PluginRepository的构造函数:

public PluginRepository(Configuration conf) throws RuntimeException {

    fActivatedPlugins = new HashMap<String, Plugin>();

    fExtensionPoints = new HashMap<String, ExtensionPoint>();

    this.conf = conf;

    this.auto = conf.getBoolean("plugin.auto-activation", true);

    String[] pluginFolders = conf.getStrings("plugin.folders");

    PluginManifestParser manifestParser = new PluginManifestParser(conf,

           this);

    Map<String, PluginDescriptor> allPlugins = manifestParser

           .parsePluginFolder(pluginFolders);

    Pattern excludes = Pattern.compile(conf.get("plugin.excludes", ""));

    Pattern includes = Pattern.compile(conf.get("plugin.includes", ""));

    Map<String, PluginDescriptor> filteredPlugins = filter(excludes,

           includes, allPlugins);

    fRegisteredPlugins = getDependencyCheckedPlugins(filteredPlugins,

           this.auto ? allPlugins : filteredPlugins);

    installExtensionPoints(fRegisteredPlugins);

    try {

       installExtensions(fRegisteredPlugins);

    } catch (PluginRuntimeException e) {

       LOG.fatal(e.toString());

       throw new RuntimeException(e.getMessage());

    }

    displayStatus();

}

         这里拷贝一点《Nutch插件系统浅析》里的介绍:

1.       plugin.folders:插件所在的目录,缺省位置在 plugins 目录下。

<property>

    <name>plugin.folders</name>

    <value>plugins</value>

</property>

2.       plugin.auto-activation:当被配置为过滤(即不加载),但是又被其他插件依赖的时候,是否自动启动,缺省为 true

<property>

  <name>plugin.auto-activation</name>

  <value>true</value>

</property>

3.        plugin.includes:要包含的插件名称列表,支持正则表达式方式定义。

<property>

  <name>plugin.includes</name>

  <value>protocol-http|urlfilter-regex|parse-(text|html|js)|index-(basic|anchor)

    |query-(basic|site|url)|response-(json|xml)|summary-basic|scoring-opic|

    urlnormalizer-(pass|regex|basic)

  </value>

</property>

4.        plugin.excludes:要排除的插件名称列表,支持正则表达式方式定义。

<property>

  <name>plugin.excludes</name>

  <value></value>

</property>

         构造函数中的filter是将所有includes加入,excludes排除,下面是一段代码:

for (PluginDescriptor plugin : plugins.values()) {

    String id = plugin.getPluginId();

 

    if (!includes.matcher(id).matches()) {

       continue;

    }

    if (excludes.matcher(id).matches()) {

       continue;

    }

    map.put(plugin.getPluginId(), plugin);

}

         如果在includes里不包含排除,如果在excludes里包含,排除。回到构造函数中,如果autotrue,则安装全部插件,如果为false则只安装过滤过的。

         现在看PluginManifestParser的构造函数:

public PluginManifestParser(Configuration conf,

        PluginRepository pluginRepository) {

    this.conf = conf;

    this.pluginRepository = pluginRepository;

}

         接下来看parsePluginFolder

public Map<String, PluginDescriptor> parsePluginFolder(

       String[] pluginFolders) {

    Map<String, PluginDescriptor> map = new HashMap<String,

        PluginDescriptor>();

 

    for (String name : pluginFolders) {

       File directory = getPluginFolder(name);

       if (directory == null) {

           continue;

       }

 

       for (File oneSubFolder : directory.listFiles()) {

           if (oneSubFolder.isDirectory()) {

              String manifestPath = oneSubFolder.getAbsolutePath()

                     + File.separator + "plugin.xml";

              try {

                  PluginDescriptor p = parseManifestFile(manifestPath);

                  map.put(p.getPluginId(), p);

              }

           }

       }

    }

    return map;

}

         默认的pluginFolders[plugins],将plugins下面的子目录下的plugin.xml取到,然后解析这个xmlparseManifestFile的代码如下:

private PluginDescriptor parseManifestFile(String pManifestPath)

       throws MalformedURLException, SAXException, IOException,

       ParserConfigurationException {

    Document document = parseXML(new File(pManifestPath).toURL());

    String pPath = new File(pManifestPath).getParent();

    return parsePlugin(document, pPath);

}

         这已经都非常细节了,将xml解析后得到document,得到它的父目录地址后,调用parsePlugin,这个就更细节了,还是拷贝一段解释:

   1.  runtime 属性描述了其需要的 Jar 包,和发布的 Jar

   2. requires 属性描述了依赖的插件

   3. extension-point 描述了本插件宣布可扩展的扩展点

   4. extension 属性则描述了扩展点的实现

典型的插件定义:

<plugin

    id="query-url" 插件的ID

    name="URL Query Filter"  插件的名字

    version="1.0.0"  插件的版本

    provider-name="nutch.org"> 插件的提供者ID

 

    <runtime>

        <library name="query-url.Jar"> 依赖的Jar

            <export name="*"/>  发布的Jar

        </library>

    </runtime>

 

    <requires>

        <import plugin="nutch-extensionpoints"/> 依赖的插件

    </requires>

 

    <extension id="org.apache.nutch.searcher.url.URLQueryFilter" 扩展的ID

        name="Nutch URL Query Filter"  扩展的名字

        point="org.apache.nutch.searcher.QueryFilter"> 扩展的扩展点ID

        <implementation id="URLQueryFilter" 实现的ID

            class="org.apache.nutch.searcher.url.URLQueryFilter"> 实现类

            <parameter name="fields" value="url"/> 实现的相关属性

        </implementation>

    </extension>

</plugin>

         感觉还有一点代码比较重要:

private void installExtensions(List<PluginDescriptor> pRegisteredPlugins) throws PluginRuntimeException {

    for (PluginDescriptor descriptor : pRegisteredPlugins) {

       for (Extension extension : descriptor.getExtensions()) {

           String xpId = extension.getTargetPoint();

           ExtensionPoint point = getExtensionPoint(xpId);

           if (point == null) {

           }

           point.addExtension(extension);

       }

    }

}

这里相当于是把所有的实现对应到相同的Extension point上。

最后调用:

private void installExtensionPoints(List<PluginDescriptor> plugins) {

    for (PluginDescriptor plugin : plugins) {

       for (ExtensionPoint point : plugin.getExtenstionPoints()) {

           String xpId = point.getId();

           fExtensionPoints.put(xpId, point);

       }

    }

}

         这里把extensionidExtensionPoint对加入到fExtensionPoints里。

         URLNormalizers里得到所有扩展是很简单的:

Extension[] extensions = this.extensionPoint.getExtensions();

         实例化一个URLNormalizer

normalizer = (URLNormalizer) ext.getExtensionInstance();

         getExtensionInstance的代码:

public Object getExtensionInstance() throws PluginRuntimeException {

    // Must synchronize here to make sure creation and initialization

    // of a plugin instance and it extension instance are done by

    // one and only one thread.

    synchronized (getId()) {

       try {

           PluginClassLoader loader = fDescriptor.getClassLoader();

           Class extensionClazz = loader.loadClass(getClazz());

           // lazy loading of Plugin in case there is no instance of the

           // plugin already.

           this.pluginRepository.getPluginInstance(getDescriptor());

           Object object = extensionClazz.newInstance();

           if (object instanceof Configurable) {

              ((Configurable) object).setConf(this.conf);

           }

           return object;

       }

    }

}

         fDescriptor.getClassLoader函数里加入相关的库之类的。

 

 

 

 

 

 

 

 

  评论这张
 
阅读(1556)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017