2021SC@SDUSC【软件工程应用与实践】Cocoon项目15——sitemap-impl文件夹分析(4)

2021SC@SDUSC

EnvironmentHelper.java

1、总结

  1. 用于维护环境堆栈的助手类,这是一个内部类,它可能会随着时间的推移以不兼容的方式发生变化。 对于基于 Cocoon 开发自己的组件/应用程序时,不应该真的需要它
  2. 属于内部类,不要使用,可以在没有警告或弃用周期的情况下删除
  3. 继承自org.apache.cocoon.util.AbstractLogEnabled
    实现了org.apache.cocoon.environment.SourceResolver, Serviceable, Disposable接口

2、主要属性

//环境信息
static protected final ThreadLocal environmentStack = new ThreadLocal();
//真正的源解析器
protected org.apache.excalibur.source.SourceResolver resolver;
//服务经理
protected ServiceManager manager;
//完整的前缀
protected String prefix;
//上下文路径
protected String context;
//从请求 uri 中剥离的最后一个前缀
protected String lastPrefix;

3、方法

构造函数:

public EnvironmentHelper(URL context) {
    if (context != null) {
        this.context = context.toExternalForm();
    }
}
public EnvironmentHelper(EnvironmentHelper parent) {
    this.context = parent.context;
    this.lastPrefix = parent.lastPrefix;
    this.prefix = parent.prefix;
}

public void changeContext(Environment env) throws ProcessingException

  • 改变环境的上下文
  • 参数env:要改变的环境
  • 在方法中我们不需要检查 uri 开头的斜线 - 前缀总是以斜线结尾
public void service(ServiceManager avalonManager) throws ServiceException {
    this.manager = avalonManager;
    this.resolver = (org.apache.excalibur.source.SourceResolver)
                      this.manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE);
    Source source = null;
    try {
        source = this.resolver.resolveURI(this.context);
        this.context = source.getURI();

    } catch (IOException ioe) {
        throw new ServiceException("EnvironmentHelper", "Unable to resolve environment context. ", ioe);
    } finally {
        this.resolver.release(source);
    }
}
  • Serviceable接口的实现,将ServiceManager 传递给 Serviceable。 Serviceable 实现应该使用指定的 ServiceManager 来获取执行所需的组件
  • Serviceable 是一个需要使用“角色”抽象连接到软件组件的类,因此不依赖于特定的实现,而是依赖于行为接口。
  • 围绕 Serviceable 的契约是它是一个用户。 Serviceable 能够使用由它初始化的 ServiceManager 管理的对象。 作为与系统契约的一部分,实例化实体必须在 Serviceable 被认为有效之前调用服务方法
  • 参数avalonManager:此 Serviceable 使用的 ServiceManager,不能为null
public void dispose() {
        if ( this.manager != null ) {
            this.manager.release( this.resolver );
            this.resolver = null;
            this.manager = null;
        }
    }
  • disposable接口的实现,在组件生命周期结束时调用 dispose 操作。 此方法将在 Startable.stop() 方法之后调用(如果由组件实现)。 组件使用此方法释放和销毁组件拥有的任何资源
  • 当组件需要在销毁之前释放和处置资源时使用 Disposable 接口
public Source resolveURI(final String location,
                             String baseURI,
                             final Map    parameters)
    throws IOException {
        return this.resolver.resolveURI(location,
                                        (baseURI == null ? this.context : baseURI),
                                        parameters);
}
  • SourceResolver接口的实现,获取源对象
  • 参数location:要解析的 URI。如果这是相对的,则它要么相对于基本参数(如果不为空)要么相对于源解析器本身的基本设置进行解析
  • 参数baseURI:用于解析相对位置的基本 URI。这是可选的,可以为null
  • 参数parameters:URI 的附加参数,参数特定于所使用的方案
public static void enterProcessor(Processor   processor, Environment env)
      throws ProcessingException
  • 每次输入站点地图时,站点地图都必须调用此钩子
  • 此方法不应引发异常,除非未设置参数,当参数为空时抛出ProcessingException
static public ServiceManager getSitemapServiceManager() {
        final EnvironmentStack stack = (EnvironmentStack) environmentStack.get();
        if (stack != null && !stack.isEmpty()) {
            return (ServiceManager) WebAppContextUtils.getCurrentWebApplicationContext().getBean(AvalonUtils.SERVICE_MANAGER_ROLE);
        }
        return null;
}
  • 获取当前的站点地图组件管理器。
  • 此方法返回当前站点地图组件管理器。 这是保存当前处理的(子)站点地图的所有组件的管理器。是内部方法,不要使用,可以在没有警告或弃用周期的情况下删除
public static void leaveProcessor()
  • 每次留下站点地图时,站点地图都必须调用此钩子
  • 它与 enterProcessor(Processor, Environment) 方法相对应
public static XMLConsumer createPushEnvironmentConsumer(XMLConsumer consumer, Environment environment)
  • 创建一个环境感知 xml 消费者,在调用消费者之前推送环境
public static XMLConsumer createPopEnvironmentConsumer(XMLConsumer consumer)
  • 创建一个环境感知 xml 消费者,在调用消费者之前弹出并保存当前环境
public static abstract class AbstractCocoonRunnable implements Runnable {
        private Object parentStack = null;
        public AbstractCocoonRunnable() {
            // 克隆调用线程的环境堆栈
            //我们将在下面的 run() 中使用它
            Object stack = EnvironmentHelper.environmentStack.get();
            if (stack != null) {
                this.parentStack = ((EnvironmentStack)stack).clone();
            }
        }
        //在创建线程的环境上下文中调用 doRun()
        public final void run() {
            // 从父线程安装堆栈并运行 Runnable
            Object oldStack = environmentStack.get();
            EnvironmentHelper.environmentStack.set(this.parentStack);
            try {
                doRun();
            } finally {
                // 恢复之前的堆栈
                EnvironmentHelper.environmentStack.set(oldStack);
            }
        }
        abstract protected void doRun();
}
  • 一个可运行的包装器,它继承了创建它的线程的环境堆栈。
  • 它在这里被定义为一个抽象类来使用 EnvironmentHelper 的一些内部结构,并且只能通过其公共对应物 org.apache.cocoon.environment.CocoonRunnable 使用
  • run():与父线程相比,检查此运行的生命周期,CocoonThread 意味着在父请求的执行周期内开始和消亡,如果由于父环境不再有效而存活时间更长,则它是一个错误

EnvironmentStack.java

1、总结

  1. 处理环境的堆栈,是用于处理 cocoon 协议和站点地图源解析的堆栈的特殊实现
  2. 这是一个内部类,它可能会随着时间的推移以不兼容的方式发生变化。对于基于 Cocoon 开发自己的组件应用程序,您不应该真的需要它

2、方法

final class EnvironmentChanger
implements XMLConsumer {

    final XMLConsumer consumer;
    final EnvironmentStack stack;
    final int oldOffset;
    final int newOffset;

    EnvironmentChanger(XMLConsumer consumer, EnvironmentStack es,
                       int oldOffset, int newOffset) {
        this.consumer = consumer;
        this.stack = es;
        this.oldOffset = oldOffset;
        this.newOffset = newOffset;
    }

    public void setDocumentLocator(Locator locator) {
        this.stack.setOffset(this.oldOffset);
        this.consumer.setDocumentLocator(locator);
        this.stack.setOffset(this.newOffset);
    }

    public void startDocument()
    throws SAXException {
        this.stack.setOffset(this.oldOffset);
        this.consumer.startDocument();
        this.stack.setOffset(this.newOffset);
    }

    public void endDocument()
    throws SAXException {
        this.stack.setOffset(this.oldOffset);
        this.consumer.endDocument();
        this.stack.setOffset(this.newOffset);
}
}
  • 这个类是一个改变当前环境的 XMLConsumer
  • 当管道调用内部管道时,会建立两种环境:一种用于调用管道,一种用于内部管道
  • 现在,如果 SAX 事件是从内部管道发送的,它们会被调用管道的某个组件接收,因此在这之间我们必须来回改变环境
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值