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

2021SC@SDUSC

sitemap-impl文件夹分析(1)


本次代码主要解析的是sitemap-impl文件夹下的components文件夹

AbstractInterpreter.java

1、总结

  1. Cocoon 用于流量控制的各种脚本语言的抽象超类。 定义一些有用的行为,例如在脚本文件被修改时重新加载脚本文件的能力(在进行开发时很有用),并将控制权传递给 Cocoon 的站点地图以生成结果页面
  2. 属于不同站点地图的流解释器应该被隔离。 为了实现这一点,类实现了 SingleThreaded。 由于站点地图引擎在站点地图构建时查找流程解释器一次,这确保每个站点地图将使用此类的不同实例。 但是该实例将处理给定站点地图的所有流调用,因此必须是线程安全的
  3. 继承自org.apache.cocoon.util.AbstractLogEnabled
    实现了Serviceable, Contextualizable, org.apache.cocoon.components.flow.Interpreter, SingleThreaded, Configurable, Disposable接口

2、主要属性:

//此解释器的实例 ID,用于标识用户范围
private String instanceID;
//是否应该重新加载脚本。 通过 flow.xmap 中的“reload-scripts”属性指定
protected boolean reloadScripts;
//两次检查修改过的脚本文件之间的间隔。 通过 flow.xmap 中的“check-time”XML 属性指定
protected long checkTime;
//需要解析的源位置列表
protected ArrayList needResolve = new ArrayList();

3、方法

public void setInterpreterID(String interpreterID)
  • 设置此解释器的唯一 ID,可用于区分附加到会话的用户值范围
public void register(String source) {
        synchronized (this) {
            needResolve.add(source);
        }
    }
  • 向解释器注册一个源文件。 使用此方法,实现会跟踪所有已编译的脚本文件。 这允许他们重新加载在文件系统上修改的脚本文件
  • 解释器对脚本文件的解析/编译分两个阶段进行。 在第一阶段,文件的位置在needResolve 数组中注册。
  • 只有当 Cocoon 环境传递给解释器时,第二种才有可能。 这允许使用 Cocoon 的 SourceFactory 类来解析文件位置
  • 一旦可以解析文件的位置,就会将其从 needResolve 数组中删除并放入脚本哈希表中。 这个哈希表中的键是文件位置字符串,值是一个 DelayedRefreshSourceWrapper 实例,用于跟踪文件何时需要重新读取
  • 参数source:脚本的位置
public synchronized final void refresh() {
        this.nextCheckTime = System.currentTimeMillis() + this.delay;
        // 调用refresh(),刷新可修改源
        this.source.refresh();
        // 保留上次修改日期
        this.lastModified = source.getLastModified();
}
  • 强制刷新包装的 Source ,即使刷新期未结束,并开始新的时期
  • 此方法是线程安全的,即使底层 Source不是

ContinuationsManagerImpl.java

1、总结

ContinuationsManager 的默认实现,有两种工作模式:

  1. 标准模式 - 延续存储在单个持有人中。没有安全性应用于继续查找,任何人都可以只知道 ID 来调用延续。 将“session-bound-continuations”配置选项设置为 false 以激活此模式
  2. 安全模式 - 每个会话都有自己的延续持有者。延续仅对为其创建的同一会话有效,会话失效也会导致所有绑定的延续失效。将此设置用于 Web 应用程序。 将“session-bound-continuations”配置选项设置为 true 以激活此模式

继承自org.apache.cocoon.util.AbstractLogEnabled
实现了 Configurable, ThreadSafe, Serviceable, Contextualizable接口

2、主要属性

//用于创建连续 ID 的随机数生成器
protected SecureRandom random;
protected byte[] bytes;
//自上次访问以来,内存中的延续存在时间。时间以毫秒为单位,默认为 1 小时
protected int defaultTimeToLive;
//维护 WebContinuation 树的森林
//此集合仅用于 displayAllContinuations()方法的调试
protected Set forest = Collections.synchronizedSet(new HashSet());
//主要延续持有人,除非延续存储在用户会话中,否则使用
protected WebContinuationsHolder continuationsHolder;
//WebContinuation 实例的排序集,基于它们的到期时间,后台线程使用它来使延续无效
protected SortedSet expirations = Collections.synchronizedSortedSet(new TreeSet());
protected boolean bindContinuationsToSession;
protected long expirationCheckInterval;

3、方法

protected void handleLeafContinuationExpiration(WebContinuation wk) 
  • 当在createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer) 中创建新的延续时,它会注册到到期集中,以便由失效机制进行评估
protected void handleParentContinuationExpiration(WebContinuation parent)
  • 当在createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer) 中创建新的延续时,其父延续将从到期集中删除。这样,只有叶子延续是到期集的一部分
protected WebContinuation generateContinuation(Object kont,
                                                 WebContinuation parent,
                                                 int ttl,
                                                 String interpreterId,
                                                 ContinuationsDisposer disposer) {

        char[] result = new char[bytes.length * 2];
        WebContinuation wk;
        WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(true);
        while (true) {
            random.nextBytes(bytes);

            for (int i = 0; i < CONTINUATION_ID_LENGTH; i++) {
                byte ch = bytes[i];
                result[2 * i] = Character.forDigit(Math.abs(ch >> 4), 16);
                result[2 * i + 1] = Character.forDigit(Math.abs(ch & 0x0f), 16);
            }
            final String id = new String(result);
            synchronized (continuationsHolder) {
                if (!continuationsHolder.contains(id)) {
                    if (this.bindContinuationsToSession)
                        wk = new HolderAwareWebContinuation(id, kont, parent,
                                                            ttl, interpreterId, disposer,
                                                            continuationsHolder);
                    else
                        wk = new WebContinuation(id, kont, parent, ttl,
                                                 interpreterId, disposer);
                    continuationsHolder.addContinuation(wk);
                    break;
                }
            }
        }
        wk.setLogger(getLogger());
        return wk;
}
  • 创建 WebContinuation 并为其生成唯一标识符。 标识符是使用加密算法生成的,以防止人们生成自己的标识符
  • 它具有将延续对象插入到 idToWebCont 哈希表中的副作用
  • 参数kont:表示延续的 Object 值
  • 参数parent:表示父 WebContinuation 的值
  • 参数ttl:WebContinuation的生存时间
  • 参数interpreterId:调用连续创建的解释器的 id
  • 参数disposer:用于清理延续的 ContinuationsDisposer 实例
  • 返回:生成的具有唯一标识符的 WebContinuation
protected void removeContinuation(WebContinuationsHolder continuationsHolder,
            WebContinuation wk) {
        if (wk.getChildren().size() != 0) {
            return;
        }
        // 删除对这个 contination 的访问
        disposeContinuation(continuationsHolder, wk);
        _detach(wk);
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("WK: Deleted continuation: " + wk.getId());
        }
        // 现在检查是否需要删除父级
        WebContinuation parent = wk.getParentContinuation();
        if (null != parent && parent.hasExpired()) {
            //父级必须具有相同的延续持有者,不需要查找            removeContinuation(continuationsHolder, parent);
        }
}
  • 从其延续树中删除过期的叶子 WebContinuation 节点,如果它们已过期且没有(其他)子节点,则递归删除其父节点
  • 调用_detach()将此延续与父级分离。此方法从森林集合中删除连续性,或者,如果它有父级,则从父级的子级集合中删除
  • 调用disposeContinuation(continuationsHolder, wk)使继续无法访问以进行查找,并通过 ContinuationsDisposer 接口触发可能需要的清理代码
protected void invalidateContinuations(WebContinuationsHolder continuationsHolder)
  • WebContinuationsHolder 用于通知 continuation 管理器有关会话失效的方法。 使传递的 continuationsHolder 持有的所有延续无效
  • 该方法中避免了 ConcurrentModificationException,这仍然不是最好的解决方案,应该改变

4、构造器

public HolderAwareWebContinuation(String id,
                                  Object continuation,
                                  WebContinuation parentContinuation,
                                  int timeToLive,
                                  String interpreterId,
                                  ContinuationsDisposer disposer,
                                  WebContinuationsHolder continuationsHolder) {
            super(id, continuation, parentContinuation, timeToLive, interpreterId, disposer);
            this.continuationsHolder = continuationsHolder;
        }

FlowHelper.java

1、总结

提供流控制器层和视图层之间的接口

视图可以获取流脚本发送的上下文对象和当前的 Web 延续(如果有)

2、主要属性

定义对象模型中用于存储各种对象的键的常量。 这些常量是私有的,因此对这些对象的访问只能通过下面提供的访问器

这些对象存储在对象模型中而不是作为请求属性存储,因为对象模型是为子请求克隆的(请参阅 EnvironmentWrapper),而请求属性在“真实”请求及其所有子请求之间共享

//用于存储流上下文的请求属性名称
private static final String CONTEXT_OBJECT = "cocoon.flow.context";
//用于存储流延续的请求属性名称
private static final String CONTINUATION_OBJECT = "cocoon.flow.continuation";

3、方法

public final static Object getContextObject(Map objectModel)
  • 获取与当前请求关联的流上下文对象
  • 参数objectModel:Cocoon 环境的对象模型
public final static void setContextObject(Map objectModel, ObjectModel newObjectModel, Object obj)
  • 设置与当前请求关联的流上下文对象
  • 参数objectModel:Cocoon 环境的对象模型
  • 参数obj:上下文对象
上一篇:System.Threading.Mutex的使用方法


下一篇:C++ 访问控制