2021SC@SDUSC [application and practice of software engineering] Cocoon code analysis


This blog is a continuation of the previous blog. First, analyze the remaining code in the avalon folder in the spring folder, and then continue to analyze the contents of other folders under the core folder. It includes the logger under the spring folder, avalon under the xml folder, and some other java files under the core folder. Due to a lot of content, I may choose to focus on analysis. I'll just take some classes that are not very focused.


This factory bean adds simple pool support to Spring.

Some attributes that need attention:

Attribute nameAttribute description
beanFactoryCorresponding bean factory
DEFAULT_MAX_POOL_SIZEDefault maximum size of the pool
interfacesAll interfaces of the agent
nameHybrid component
semaphoreObject to synchronize access to get and put methods


Overload, create a PoolableComponentHandler to manage the component pool created by the specified factory object.

public PoolableFactoryBean( String name, String className )
throws Exception {
    this(name, className, DEFAULT_MAX_POOL_SIZE, null);

public PoolableFactoryBean( String name, String className, String poolMaxString, Settings settings )
throws Exception {
    String value = poolMaxString;
    if ( settings != null ) {
        value = PropertyHelper.replace(poolMaxString, settings);
    int poolMax = Integer.valueOf(value).intValue();
    this.name = name;
    this.max = ( poolMax <= 0 ? Integer.MAX_VALUE : poolMax );
    this.beanClass = Class.forName(className);
    final HashSet workInterfaces = new HashSet();
    //Get all interfaces
    this.guessWorkInterfaces( this.beanClass, workInterfaces );
    //Add AvalonPoolable
    this.interfaces = (Class[]) workInterfaces.toArray( new Class[workInterfaces.size()] );
    //Create pool list
    this.ready = new LinkedList();

Other important methods:


Process associated pools and factories.

public void dispose() {
    //Any Poolables in the preparation list need to be processed
    synchronized( this.semaphore ) {
        //Remove objects from the preparation list
        for( Iterator iter = this.ready.iterator(); iter.hasNext(); ) {
            Object poolable = iter.next();
            this.permanentlyRemovePoolable( poolable );


Process service specific methods and put them into the pool

protected void enteringPool( final Object component ) {
    try {
        //Processing recyclable objects
        if( component instanceof Recyclable ) {
            ( (Recyclable)component ).recycle();
        if ( this.poolInMethod != null ) {
            this.poolInMethod.invoke(component, null);
    } catch (Exception ignore) {
        //During the process of putting the component back into the pool, we ignore the exception because it will not cause the system to crash -- this is for compatibility with the original Avalon implementation
        this.log.error("Exception while putting component '" + component + "' back into the pool.", ignore);


Process service specific methods and remove them from the pool

protected void exitingPool( final Object component )
throws Exception {
    if ( this.poolOutMethod != null ) {
        this.poolOutMethod.invoke(component, null);


Get a Poolable from the pool.

If there is space in the pool, a new Poolable is created. Depending on the parameters of the constructor, the method may block or throw an exception if Poolable on the pool is not available.

public Object getFromPool() throws Exception {
    Object poolable;
    synchronized( this.semaphore ) {
        //In M_ Find Poolable at the end of the ready list
        if ( this.readySize > 0 ){
            //poolable is ready and waiting in the pool
            poolable = this.ready.removeLast();
        } else {
            //Create a new poolable. If the pool cannot be instantiated, an exception may be thrown.
            poolable = this.beanFactory.getBean(this.name);
            this.highWaterMark = (this.highWaterMark < this.size ? this.size : this.highWaterMark);
    return poolable;


Permanently delete a pool from the pool's active list and destroy it so that it will never be reused

This method is only locked m_ Thread call of semaphore.

protected void permanentlyRemovePoolable( Object poolable ) {


Return pool object to pool

public void putIntoPool( final Object poolable ) {
    synchronized( this.semaphore ) {
        if( this.size <= this.max ) {
            this.ready.addLast( poolable );
        } else {
            //Create more Poolables than the pool can hold, so please delete.
            this.permanentlyRemovePoolable( poolable );

7. Guess workinterfaces() and addInterfaces():

Get the interface list of the agent by scanning all interfaces implemented by a class

private void guessWorkInterfaces( final Class clazz,
                                  final Set workInterfaces ) {
    if ( null != clazz ) {
        this.addInterfaces( clazz.getInterfaces(), workInterfaces );

        this.guessWorkInterfaces( clazz.getSuperclass(), workInterfaces );
private void addInterfaces( final Class[] classInterfaces,
                           final Set workInterfaces ) {
    for ( int i = 0; i < classInterfaces.length; i++ ) {
        workInterfaces.add( classInterfaces[i] );
        this.addInterfaces(classInterfaces[i].getInterfaces(), workInterfaces);


There are two important attributes:

  • Default location for spring related child configuration files

There are some methods worth analyzing:


Add header of xml configuration file

protected static void addHeader(StringBuffer buffer) {
    buffer.append("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
    buffer.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
    buffer.append(" xmlns:util=\"http://www.springframework.org/schema/util\"");
    buffer.append(" xmlns:configurator=\"http://cocoon.apache.org/schema/configurator\"");
    buffer.append(" xmlns:avalon=\"http://cocoon.apache.org/schema/avalon\"");
    buffer.append(" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd");
    buffer.append(" http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd");
    buffer.append(" http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.xsd");
    buffer.append(" http://cocoon.apache.org/schema/avalon http://cocoon.apache.org/schema/avalon/cocoon-avalon-1.0.xsd\">\n");


Add footer for xml configuration file

protected static void addFooter(StringBuffer buffer) {


If the xml stream has a value, add an attribute to it

protected static void addAttribute(StringBuffer buffer, String name, String value) {
    if ( value != null ) {
        buffer.append(' ');


Judge whether to read the site map by default

protected static boolean isUsingDefaultIncludes(Configuration config) {
    return config.getChild("components").getAttributeAsBoolean("use-default-includes", true);


Get all the contained information of the bean configuration from the site map

protected static List getBeanIncludes(WebApplicationContext webAppContext,
                                      String                contextUrl,
                                      Configuration         sitemap)
throws ConfigurationException {
    final List includes = new ArrayList();
    if ( isUsingDefaultIncludes(sitemap) ) {
        final Resource rsrc = webAppContext.getResource(contextUrl + DEFAULT_CHILD_SPRING_CONFIGURATION_LOCATION);
        if ( rsrc.exists() ) {
    final Configuration[] includeConfigs = sitemap.getChild("components").getChildren("include-beans");
    for(int i = 0 ; i < includeConfigs.length; i++ ) {
        final String dir = includeConfigs[i].getAttribute("dir");
    return includes;


Get all contains of properties from site map

protected static List getPropertiesIncludes(WebApplicationContext webAppContext,String contextUrl,Configuration sitemap)
throws ConfigurationException {
    final List includes = new ArrayList();
    if ( isUsingDefaultIncludes(sitemap) ) {
        final Resource rsrc = webAppContext.getResource(contextUrl + DEFAULT_CHILD_PROPERTIES_LOCATION);
        if ( rsrc.exists() ) {
    final Configuration[] includeConfigs = sitemap.getChild("components").getChildren("include-properties");
    for(int i = 0 ; i < includeConfigs.length; i++ ) {
        final String dir = includeConfigs[i].getAttribute("dir");

    return includes;java


Create each site map container

public static WebApplicationContext createContainer(Configuration  config,String sitemapLocation,Monitor fam,ServletContext servletContext)
    throws Exception {
        //Get parent container first
        final WebApplicationContext parentContext = WebAppContextUtils.getCurrentWebApplicationContext();
        final ProcessInfoProvider infoProvider = (ProcessInfoProvider) parentContext.getBean(ProcessInfoProvider.ROLE);
        final Request request = ObjectModelHelper.getRequest(infoProvider.getObjectModel());
        //Determine context url
        int pos = sitemapLocation.lastIndexOf('/');
        if ( sitemapLocation.lastIndexOf(File.separatorChar) > pos ) {
            pos = sitemapLocation.lastIndexOf(File.separatorChar);
        final String contextUrl = sitemapLocation.substring(0, pos + 1);
        //Get class loader
        final ClassLoader classloader = Thread.currentThread().getContextClassLoader();        
        //Create root bean definition
        final String definition = createDefinition(request.getSitemapURIPrefix(),sitemapLocation.substring(pos+1),getBeanIncludes(parentContext, contextUrl, config),getPropertiesIncludes(parentContext, contextUrl, config),getGlobalSitemapVariables(config));
        final ChildXmlWebApplicationContext context = new ChildXmlWebApplicationContext(contextUrl,definition);
        if ( classloader != null ) {
        return context;

Other documents

Name of the classClass description
PoolableProxyHandlerAgents for all mergeable components
SettingsContextThis is an extension of the default context implementation. It first looks at the settings object and delegates to the parent object only if the key cannot be found there. This object is used to set up the logger
ChildLoggerFactoryBeanSpring factory bean to set up a child public logger
LoggerFactoryBeanThe Spring factory bean sets the public logger and the specified class. If no category is set, the default category "cocoon" is used
LoggerUtilsCommons logger utility
DefaultDOMParserWrapper implementation supporting Excalibur XML interface
DefaultResolverWrapper implementation supporting Excalibur XML interface
DefaultSAXParserWrapper implementation supporting Excalibur XML interface
WiringNotFoundExceptionIf wiring is not found XML, this exception is thrown

Keywords: Java

Added by stereo on Thu, 23 Dec 2021 08:57:12 +0200