Return-Path: Delivered-To: apmail-cocoon-dev-archive@www.apache.org Received: (qmail 55521 invoked from network); 27 Aug 2003 12:39:51 -0000 Received: from daedalus.apache.org (HELO apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 27 Aug 2003 12:39:51 -0000 Received: (qmail 22469 invoked by uid 500); 27 Aug 2003 12:39:37 -0000 Delivered-To: apmail-cocoon-dev-archive@cocoon.apache.org Received: (qmail 22401 invoked by uid 500); 27 Aug 2003 12:39:35 -0000 Mailing-List: contact dev-help@cocoon.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: dev@cocoon.apache.org Delivered-To: mailing list dev@cocoon.apache.org Received: (qmail 22366 invoked from network); 27 Aug 2003 12:39:34 -0000 Received: from unknown (HELO onramp.i95.net) (205.177.132.17) by daedalus.apache.org with SMTP; 27 Aug 2003 12:39:34 -0000 Received: from apache.org ([66.208.12.130]) by onramp.i95.net (8.12.9/8.12.9) with ESMTP id h7RCdTcY019382 for ; Wed, 27 Aug 2003 08:39:29 -0400 Message-ID: <3F4CA680.3040702@apache.org> Date: Wed, 27 Aug 2003 08:39:28 -0400 From: Berin Loritsch User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 X-Accept-Language: en-us, en MIME-Version: 1.0 To: dev@cocoon.apache.org Subject: [RT] Blocks and Really Making them Work Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N If blocks are deployment components (like WAR files and EAR files), we have ways of simply making the blocks happen. Sure we will have hundreds of small JAR files to juggle around, but it will enable us to upgrade our site one piece at a time. There are currently two issues at hand: classloader structure and required meta data. Whether you formally specify them or not doesn't really matter, they are needs. To that end, it would make sense to learn from how others solved these problems. For instance, there are two ways of solving the classloader issue--which can be used together. The first is the use of the MANIFEST.MF file to declare both the id info for the declared JAR and the dependency info for the JAR. Maven takes care of this automatically--but there is a standard already. The other is the Advanced Classloading portion of the JMX spec. Using a combination of the info and a modified JMX style classloading architecture we can get all the components we need. The simple explanation of the JMX style advanced classloading is that we have a ClassLoader repository sitting on top of a parent classloader. So the repository will be where we load the blocks, and the parent will be the Servlet classloader (or the system classloader if we are using CLI). The repository works by having an object (let's call it Block) that *is* a classloader represent each and every JAR. It's a one-to-one mapping: one JAR to one object. The semantics work as you would normally expect with one additional twist: after the Block classloader tries to load from the parent classloader and can't, it iterates through the other Block classloaders in the repository. According to the JMX specs, the order that the blocks are added is the order that they are searched--and to avoid deadlocks once we encounter our block again the search is over. We can use the information from the MANIFEST.MF file to coerce the order for any particular Block so that we can ensure all classloaders are checked and it cannot ever see itself in the list (i.e. a tad more advanced than the JMX specs). If it still can't find the requested class, it will try itself (without any worries about blocking). So what about those Blocks who would really like to have a set of JARs encapsulated inside the parent JAR? I would propose that the Block classloader mechanism be made smart enough to either use a MANIFEST.MF entry, or a special block.xml file to list the locations of all the internal JAR files. Those JAR files are only accessible from the Block classloader (i.e. they are considered private). As to unloading and reloading the Blocks (upgrading, downgrading, etc.) the Repository must be smart enough to unload that Block and all other Blocks that use it. For some central blocks, the impact will be huge. For other less central blocks, the impact will be minor. Each block should have a block.xml or similar file that establishes the configuration for any new components that need to be loaded to support the Block, as well as a laundry list of components that the Block needs in order to run. That laundry list will let the container see if the requested component is available already so that the number of new components created will be kept to a minimum. Beyond that, if there is a sitemap.xml it is mounted in the appropriate location. For something like Cocoon, where assembling a hierarchical system is very natural, there can be more than one repository--where the parent classloader is the parent repository. That will help certain things like auto-mounting of blocks relative to a particular URL. Cocoon just has to be smart enough to do some "smart-mounting". Smart-mounting involves mounting a block by name, so that a parent sitemap.xml will specify where in the URL hierarchy that the mount goes--but the actual implementation is in a compiled block. I would start with something like this, and see how far it can take you--and if there are new features required, add them. -- "They that give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." - Benjamin Franklin