2021SC@SDUSC
sitemap-impl文件夹分析(4)
EnvironmentHelper.java
1、总结
- 用于维护环境堆栈的助手类,这是一个内部类,它可能会随着时间的推移以不兼容的方式发生变化。 对于基于 Cocoon 开发自己的组件/应用程序时,不应该真的需要它
- 属于内部类,不要使用,可以在没有警告或弃用周期的情况下删除
- 继承自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、总结
- 处理环境的堆栈,是用于处理 cocoon 协议和站点地图源解析的堆栈的特殊实现
- 这是一个内部类,它可能会随着时间的推移以不兼容的方式发生变化。对于基于 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 事件是从内部管道发送的,它们会被调用管道的某个组件接收,因此在这之间我们必须来回改变环境