leosimons 2003/02/05 02:28:18 Added: src/xdocs book.xml designing-a-component.xml getting-started.xml guide-cop-in-avalon.xml guide-cop-what-is.xml guide-oop-best-practices.xml guide-patterns-in-avalon.xml guide-patterns-ioc-security.xml guide-patterns-ioc.xml guide-patterns-soc.xml guide-patterns-soii.xml guide-patterns-what-are.xml guide-where-to-go-from-here.xml index.xml reference-containers.xml reference-the-lifecycle.xml tabs.xml Log: Putting in place the forrestized version of the framework docs from the proposal directory here Revision Changes Path 1.17 +27 -44 jakarta-avalon/src/xdocs/book.xml 1.1 jakarta-avalon/src/xdocs/designing-a-component.xml Index: designing-a-component.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Designing a Component</title> <version>1.0</version> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>How is the Component Going to be Used?</title> <p> The first step in writing the component is determining how it is going to be used. There will be a number of times where you have a powerful component that can be used in many different contexts. Those contexts may include executing the component from the command line (separate from Avalon), using it as a part of a sub system, or using it as an integral part of Avalon. </p> <section> <title>Part of Avalon</title> <p> All components are an integral part of Avalon, so there is really nothing to be done beyond specifying its interface (role). It is important to identify and document its social contract with the rest of the system. What I mean by social contract is the order of dependencies, what it needs to function, and what it supplies to the rest of the system. </p> </section> <section> <title>Part of a Sub System</title> <p> A sub system can either be part of Avalon, or live in a separate context. A perfect example would be a component that can function within a Servlet or Enterprise Application. Neither of those contexts are native to Avalon (though they can easily be built on top of Avalon). </p> <p> It is important to do even more careful planning than in the first scenario. The reason is that you want the interface to be as generic as possible and still accurately represent its role. </p> <p> Because the contexts may not be an integral part of Avalon, you must take care to use the component in the same manner as Avalon would. That means that you follow the order of concerns that Avalon has specified for those concerns. </p> </section> <section> <title>A Stand Alone Program</title> <p> When you are designing a component to be run from the command line (or directly by the operating system), try to separate the main function from the component itself. This is imperative in order to maintain the passive API of Avalon. By designing your component in the manner stated in the previous section, you have effectively minimized what the main function has to do. </p> <p> Follow the practice of having an object dedicated to the main function that includes the parsing of the command line parameters and initialization of the component. When the component is used the exact same way in every context (including the command line), you minimize the number of locations to look while debugging. </p> <note> A common mistake is to combine the main function in the implementation of the component. This requires violating the contracts and principles that Avalon is built upon. This violation of the pattern of "Inversion of Control" is aptly dubbed "Subversion of Control" (thanks to Steven Coffman for the name of the anti-pattern). </note> </section> </section> </body> </document> 1.8 +36 -87 jakarta-avalon/src/xdocs/getting-started.xml 1.1 jakarta-avalon/src/xdocs/guide-cop-in-avalon.xml Index: guide-cop-in-avalon.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - COP in Avalon</title> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Components in Avalon</title> <p> At the core of the Avalon framework is the component. We define it as "a passive entity that performs a specific role". This is important to grasp because it requires a specific way of thinking. </p> <section> <title>A passive API</title> <p> A passive entity must employ a passive API. A passive API is one that is acted upon, versus one that acts itself. See the <link href="guide-patterns-ioc.html">Inversion of Control</link> pattern for an explanation. </p> </section> <section> <title>A specific Role</title> <p> The concept of roles comes from the theater. A play, musical, or movie will have a certain number of roles that actors play. Although there never seems to be a shortage of actors, there are a finite number of roles. I am not going to make reference to different types of roles at this point, but simply bring the concept to light. The function or action of a role is defined by its script. </p> <p> We are introducing this concept now because you need to have it in mind when you are designing your system architecture. Think of the different roles in your system, and you will have your "cast" of components so to speak. </p> <p> For each role, you need to specify its script, or interface to the rest of the system. To be honest the interface is not enough. There are specific contracts that you must define and keep in mind when you specify your interfaces. In other words, what users of the component must provide, and what the component produces. When the interfaces and contracts are defined, you can work on your implementation. </p> </section> </section> <section> <title>The Component</title> <p> John Donne wrote, "No man is an island." to communicate that we are all interdependent. The same is true for the component. That is why there are different concerns regarding the component. In the section on roles we specified one of the concerns: the role. The concerns directly supported by the Avalon Framework are: configuration, external component use, management, and execution. </p> <note> We used to have a marker interface component. This has been deprecated because requiring all components extend this interface makes integrating Avalon with other component systems like <link href="http://www.corba.org">CORBA</link> very cumbersome. </note> <p> As you might have guessed, each one of these concerns has a separate interface that describes that concern. We will delve deeper into the interfaces and the reasoning behind them in other sections. It is important to know the order of precedence for the concerns so that you know the overall contracts of how they are put together. </p> <ol> <li> <strong>Configurable:</strong> marks an object that can be configured. </li> <li> <strong>Composable:</strong> marks an object that uses Components. </li> <li> <strong>Initializable:</strong> marks an object that can be initialized. </li> <li> <strong>Disposable:</strong> marks an object that can be disposed. </li> <li> <strong>Stoppable:</strong> marks an object that can be started and stopped. </li> </ol> <p> The contract surrounding this order means that the methods defined by each of those interfaces are called in a specific order by the object that created the component. Each interface represents a narrow view of the component or object being controlled. </p> <note> Notice that each interface is separate from Component, so you can use them for simple objects. </note> </section> <section> <title>The Composable</title> <p> In Avalon, Composable is defined as an active entity that controls or uses components. Its best analogy is that of a musical composer. The musical composer chooses instruments (components) by their role in the symphony (system) and tells them which notes to play. </p> <p> The Avalon Composable follows the principles of Inversion of Control, and is assigned a Component Manager. Within this section we will discuss how to look up specific components, and then how to prepare the ComponentManager for the Composable. </p> <note> The Composable has a specific contract that must be enforced for security reasons. The ComponentManager must only be set once. That means that the <code>compose</code> method must ignore all subsequent requests to set the ComponentManager after it is successfully set. </note> </section> <section> <title>Finding your Component</title> <section> <title>The Component Manager</title> <p> For the majority of all cases, you will need to use the ComponentManager to get the instance of the component you need. If you recall the discussion on component roles in the component documentation, you already have a head start. In Avalon, roles are defined by the work interface a component has. A work interface is different from any other interface because it is the interface that defines the component's role. Composable and Component are concern interfaces because they address specific concerns about the component. </p> <p> The ComponentManager has one method to retrieve all of your components. The <code>lookup</code> method will look up the component based on the fully qualified name (FQN) of the work interface (Role). It is important to realize that the ComponentManager returns Components, and therefore you must recast the Component to the role you need. See the following example: </p> <source> final MyComponent component = (MyComponent)manager. lookup( "com.mycompany.myproject.MyComponent" ); </source> <p> It is important to note that role is not the same thing as functional equivalence. In other words, if you have a MailSpooler that is functionally equivalent to a FileStore (they do the same thing), it does not mean that they perform the same role. The FileStore is used to store objects to files, and the MailSpooler is used to temporarily store messages until they are sent. Thus they are separate roles. Some containers require that the interface name match the key used to lookup component. In this situation you may need to create a new interface that does nothing more than extend another interface and add a new role. </p> </section> <section> <title>The Component Selector</title> <p> Sometimes you will have several components that function in the same role. For those cases, you will use the ComponentSelector to choose the exact one you need. The best way to describe its proper use is the scenario described here. You have several formatters that have the same role: to take an input document and format it according to the rules in the individual component implementations. One formatter may take a text file and remove all tabs and replace them with four spaces. Another formatter may reverse the formerly mentioned one. Yet another takes the text file and formats it for a canvas object. For the Composable, it makes no difference what the implementation does--just that it formats the text. </p> <p> Using the processing chain example in the previous paragraph, we realize the unsuitability of the ComponentManager for getting the right component. The component addresses the concern of one component per role. Fortunately, the ComponentSelector is a component. That means we use the ComponentManager to lookup the ComponentSelector. The ComponentSelector is designed to choose the specific component out of many that perform the <strong>same</strong> role. The following code will help: </p> <source> final ComponentSelector selector = (ComponentSelector)manager. lookup( "org.mycompany.myproject.FormatterSelector" ); final Formatter formatter = (Formatter)selector.select( myURL ); </source> <p> The selector does not discriminate against lookup keys. In that respect it acts much like a hashtable lookup. Keep in mind that the implementation of the selector does not limit you to a hashtable lookup--you can dynamically instantiate objects as well. It takes an object (a hint), and returns the specific component based on that hint. </p> <note> Discussions are currently taking place about the ComponentSelector interface and concept. It might be deprecated at some point in the future. There are indications that usage of the ComponentSelector is only required when an application is badly designed. </note> </section> <section> <title>When you are done with the Component</title> <p> Both the ComponentManager and the ComponentSelector require you to release your component when you are done with it. The method used to do this is "release". One way of handling this is to use the try/catch/finally construct. For your convenience, the following code can help: </p> <source> MyComponent component = null; try { component = (MyComponent) manager.lookup("org.mycom.MyComponent"); component.myMethod(); } catch (Exception e) { getLogger().debug("Error using MyComponent", e); } finally { if (component != null) manager.release(component); } </source> <p> The reason for this is so that smart component managers that select components from a pool can properly manage the resources. </p> </section> </section> <section> <title>Populating the ComponentManager</title> <p> It is the responsibility of the entity that creates the Composable to give it a ComponentManager with all of the Roles populated. If you create your own implementations of the ComponentManager and ComponentSelector then you have the liberty of deciding how to populate them. Keep in mind that there are default implementations included, and you should model their behavior as much as possible. </p> <section> <title>DefaultComponentManager</title> <p> The DefaultComponentManager is nothing more than a Hashtable lookup of roles and Components. It even gives you the method <code>put</code> to populate the ComponentManager. One feature of the DefaultComponentManager is that it can cascade. In other words, if the role is not found in this ComponentManager, the default implementation will look in the parent ComponentManager. </p> <p> For the paranoid developer, the cascading feature of the ComponentManager can be seen as a security hole as opposed to a usability enhancement. You are free to create your own implementation that does not use the cascading feature--but you have to manually populate it with anything that would have been in the parent ComponentManager that your child Composable needs. Truth be told, there is very little risk due to the set-once contract for ComponentManagers. The method is never exposed to hostile agents before the ComponentManager is set. </p> </section> <section> <title>DefaultComponentSelector</title> <p> The DefaultComponentSelector again is simply a Hashtable selection of components based on hints. It gives the method <code>put</code> to populate the ComponentSelector. The ComponentSelector does not have the cascading feature of the ComponentManager, nor should it. A ComponentSelector simply holds a number of components that implement the same role--there really is no need to cascade. </p> <p> After the ComponentSelector is populated, you must put it in the ComponentManager. Please use the role of the component you are selecting, not the role of the selector itself. An acceptable convention is to add the "Selector" name to the end of the role you are looking up. Just be consistent. </p> </section> </section> <section> <title>The Container</title> <p> The container is the entity that manages your components. It handles things like loading of configuration files, resolution of dependencies, component management, component isolation, and lifecycle support. </p> <p> The container is not formalized in the form of an interface or contract within Avalon Framework, though it might be at some point in the future. The informal contract for the container is that it has the ability to host any fully Avalon-Framework compliant component. Most current containers place additional requirements on the component. </p> <p> For a list of container implementations, <link href="reference-containers.html">look here</link>. </p> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-cop-what-is.xml Index: guide-cop-what-is.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - What is COP?</title> <version>1.0</version> <authors> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> Component Oriented Programming, or COP for short, takes Object Oriented Programming one step further. Regular OOP organizes data objects into entities that take care of themselves. There are many advantages to this approach. I'll assume that you, being a Java programmer, are familiar with those. </p> <p> It also has a big limitation: that of object co-dependency. To remove that limitation, a more rigid idea had to be formalized: the component. The key difference between a regular object and a component is that a component is completely replaceable. </p> </section> <section> <title>COP is not just a Buzzword</title> <p> There is a lot of buzz in the industry touting Component Based Design (CBD). You will find, that the definition of a component in Avalon is more formal than most companies' definition of a component. Any system developed with the principles of Avalon can claim CBD. In fact the Avalon Framework formalizes CBD more rigidly than the marketing definition. Do not be fooled though, CBD and COP aren't necessarily the same thing. Component Based Design refers to how a system is designed and not how it is implemented. Component Oriented Programming, on the other hand, refers to how a system is implemented and not how it is designed. In practice, you can't implement COP without first designing with components in mind. </p> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-oop-best-practices.xml Index: guide-oop-best-practices.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - OOP best Practices</title> <authors> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> While Avalon is not really about Object-Oriented Programming (OOP) (we go much further), some of its concepts are important in any programming project, so we summarise the 12 rules for code reuse as given in <link href="http://www.laputan.org/drc/drc.html"> "Designing Reusable Classes" </link> by Ralph E. Johnson and Brian Foote (an excellent book). </p> <p> Note that a good knowledge of the basic OOP concepts is a requirement for understanding any of this. Many books deal with this, one that is freely available online is <link href="http://www.mindview.net/Books/TIJ/"> "Thinking in Java" </link> by Bruce Eckel (also a recommended read). </p> </section> <section> <title>Recursion Introduction</title> <p> Use the same interface for communication with components of the same type. It allows the swapping of those components for other components of the same type without breaking existing code. </p> <p> If you need additional functionality, either create proxy objects that implement the interface, or add it by subclassing (hence the name "Recursion Introduction"). Even if there is no recursion happening, it appears to operate in the same manner. </p> </section> <section> <title>Eliminate Case Analysis</title> <p> Avoid testing to see if an object is an instance of a particular class. Usually, if you think you need that approach then a redesign will help immensely. </p> </section> <section> <title>Reduce the Number of Arguments</title> <p> Methods with a half-dozen arguments are hard to read, and can usually be accomplished with an object that represents that set of arguments. It also makes it easier to track down the problems. </p> </section> <section> <title>Reduce the Size of Methods</title> <p> Most of your methods should only need to be a few lines long. Methods that are very long (like 50 lines or so) are too complex, and should be considered guilty of bad design until proven innocent. </p> </section> <section> <title>The Top of the Class Hierarchy Should be Abstract</title> <p> In many cases it is beneficial to provide an abstract base class to extend for your specializations. The majority of the functionality and behavior is well defined. This makes it easier to decipher what the intents of the interface designer were. </p> </section> <section> <title>Minimize Accesses to Variables</title> <p> This point formalizes the principles of data hiding. Try not to expose class attributes to other classes, but protect them by methods. If an attribute changes name, then you only have one place to update the code instead of hundreds. </p> </section> <section> <title>Subclasses Should be Specializations</title> <p> A [subclass] "is a" [superclass]. If what you are trying to do is make a Component into a ComponentManager, then you are violating the spirit of the framework. A better approach is to use containment in that case (i.e. a [class] "has a" [external class]). </p> </section> <section> <title>Split Large Classes</title> <p> If a class has 50+ methods, then it is most likely trying to do too much. Look at separating the functionality into separate components. Like methods that are too long, classes that violate this rule should be considered guilty of wrong design until proven innocent. </p> </section> <section> <title>Factor Implementation Differences Into Subcomponents</title> <p> If a subclass implements a method completely different from the superclass, then it is not really a specialization. It should be split off from that class hierarchy tree. </p> </section> <section> <title>Separate Methods that Do Not Communicate</title> <p> Sometimes in building a framework you run into a case where you have different views of the same data. In these cases, you can have some attributes that describe how to generate the data, and some attributes that describe the data itself. It is better to separate these two views into separate classes. The semantics are different enough to justify this solution. </p> </section> <section> <title>Send Messages to Components instead of to This</title> <p> The point of this point is that you want to build your framework based on components, and not inheritance. Avalon takes this point to heart. In order to illustrate, I will give two examples of the same thing. The scenario is that we have a data structure that we want to output to an arbitrary format. </p> <p> In the following example, we will use the Java <code>this</code> object and an inheritance based framework. As you can see, this would be a bear to maintain, and it won't easily be extended. </p> <source> abstract class AbstractExampleDocument { // skip some code ... public void output(Example structure) { if( null != structure ) { this.format( structure ); } } protected void format(Example structure); } </source> <p> In the next example, we will use the Avalon component based architecture. There is a clean separation between the purpose of the objects, and you can exchange and extend formatting without worrying about any other concerns. </p> <source> class DefaultExampleDocument { // skip some code ... public void output(Example structure) { ExampleFormatter formatter = (ExampleFormatter) manager.lookup(Roles.FORMATTER); if( null != structure ) { formatter.format(structure); } } } </source> <p> An inheritance based framework (White Box) can be converted into a component based framework (Black Box) structure by replacing overridden methods with method calls (message sends) to components. Component based architecture is much more flexible in this regard. </p> </section> <section> <title>Eliminate Implicit Parameter Passing</title> <p> Just because two methods share the same information within the class does not mean that it should be done in that manner. Many times, the attribute that is shared should be passed as a parameter of the method instead of directly accessing the attribute. </p> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-in-avalon.xml Index: guide-patterns-in-avalon.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Patterns in Avalon</title> <authors> <person name="Avalon Documentation Team" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Getting Started with Patterns</title> <p> Avalon takes many design patterns and architectural mindsets, and implements the best ones for servers. There are different kinds of patterns that represent different aspects of Avalon. Avalon uses four main conceptual patterns called Separation of Interface and Implementation, Inversion of Control, Multi-Dimensional Separation of Concerns, and Aspect Oriented Programming. Avalon also uses several architectural patterns like the Singleton and the Factory. </p> </section> <section> <title>The Avalon Patterns in short</title> <p> We provide you with a short description of the patterns first, with a detailed description of each pattern on a separate page. </p> <section> <title>Separation of Interface and Implementation</title> <p> <strong>Summary:</strong> The Separation of Interface and Implementation is a core feature of the Java language. However, it is often misused so we list it as one of the Avalon patterns, and our use of it is extensive. </p> <p> <link href="guide-patterns-soii.html"> More Information... </link> </p> </section> <section> <title>Inversion of Control</title> <p> <strong>Summary:</strong> Avalon not only has an inheritance hierarchy, but also a component hierarchy. In this hierarchy, the control of program flow is completely in the hands of the parent component(s), as soldiers in the military take orders from their officers. </p> <p> <link href="guide-patterns-ioc.html"> More Information... </link> </p> </section> <section> <title>Multi-Dimensional Separation of Concerns</title> <p> <strong>Summary:</strong> You just read the introduction about patterns before reading about Avalon's patterns because that enables you to reuse the knowledge you gained about patterns in a context other than that of Avalon. We do this with software as well. </p> <p> <link href="guide-patterns-soc.html"> More Information... </link> </p> </section> <section> <title>Aspect-Oriented Programming</title> <p> <strong>Summary:</strong> this is the next logical step ofter Separation of Concerns. Many concerns cannot be centrally addressed using the standard OOP mechanisms. Using AOP (which is an extension to OOP), we would be able to do so in a simple fashion. As there is no good AOP facility in Java, we use "aspect marker interfaces" and COP instead. </p> </section> <section> <title>Component-Oriented Programming</title> <p> <strong>Summary:</strong> The Avalon framework promotes black-box reuse at every level. Doing so is commonly known as COP. This is so important in Avalon we devote an <link href="guide-cop-what-is.html"> entire section </link> to it. </p> </section> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-ioc-security.xml Index: guide-patterns-ioc-security.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Security Concerns</title> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> One major concern for many companies is the security of a system. In this context security is defined as protection of data, and quality of service (QOS). Both of these fall under security because a system must protect itself from these two forms of attack. When a company loses a system, it loses business, and the money it loses can reach scary amounts. </p> <p> For the purpose of this discussion, we will address the first aspect (protection from crackers and system infiltration). Many times, the same fixes for this type of protection inherently fix the other (QOS). System security has three distinct concerns that have been well defined: authentication, authorization, and architecture. Why didn't I say encryption? It is because encryption does not equal security. It is only part of the whole system. </p> <section> <title>Authentication</title> <p> Authentication is the process of identifying parties. In a completely trusted system, authentication is as simple as grabbing a reference to the object or entity you want to manipulate. However, sometimes you have trusted systems running in hostile environments (e.g. the Internet). In those cases you have to make sure that the entity is the correct one. </p> <p> There are two sides of authentication. On one side, you are authenticating an entity you want to do business with. On the other side, there is an entity wanting to do business with you. This is best understood when you bring it into a financial realm. Let's say you want to get a loan from XYZ bank. If you initiate the exchange at their facility, you have already authenticated them--although you will have to jump through hoops to authenticate yourself. If a telemarketer calls from ACME Loan Machine, Inc., they know who you are--although if you are smart, you will make them jump through hoops to authenticate themselves. </p> <p> Currently, Avalon identifies blocks as trusted parties. In other words, the fact that they are installed correctly in the proper directory is enough to mark them as authenticated. Much like a good friend--you know them by their voice. Because of the architecture of Avalon, blocks define their own authentication system. That means that whether the block assumes all components are trusted or it forces the blocks to authenticate themselves is up to the block. </p> <p> For systems that deal with sensitive information, authentication becomes more of an issue. You must validate that the components in use are the ones you have authorized for use. The more open a system is, the more authentication and authorization play an important role. If you have components that are transmitted over some form of communications system (wire, air, etc.) you must verify that they are who they say they are. </p> <p> For this purpose, protocols like Kerberos and Leighton-Micali have been defined. It is beyond the scope of this page to discuss the pros and cons of each system. </p> </section> <section> <title>Authorization</title> <p> Once a component has been authenticated (in other words its identity has been authoritatively validated), then you must decide what access it has to your systems. A fully trusted component can do what it likes. An untrusted component must be denied functions it is not allowed. </p> <p> Authorization is part of the architecture, but is significant enough to warrant its own concern. The best rule of thumb is to hide access to everything unless the component is trusted. When hiding is not an option, then you have to resort to denying access. For the security conscious, all denied accesses should be logged along with the component's identifier. </p> </section> <section> <title>Architecture</title> <p> Avalon already has the framework for the proper secure architecture. With proper planning, security can be added without recoding the components. However there are some rules of thumb for paranoid programming. </p> <ol> <li> Never expose anything that does not need to be exposed. Information hiding is as important in security as it is in Component Oriented Programming (COP). </li> <li> Any component that originates from your own jar should be trusted--you provided it after all. </li> <li> Any component that originates from another source, and especially over a wire, should be treated with suspicion. Authenticate it, and if it checks out, trust it. Otherwise, don't give it access--you don't know where it's been or who created it. </li> <li> Encrypt <strong>all</strong> communications. Period. </li> </ol> </section> </section> <section> <title>From the Sublime to the Ridiculous</title> <p> Throughout my short career I have been exposed to a wide range of security implementations. Having worked for a DoD contractor, I learned about physical security requirements (how to manage paper files, and the rules and regulations regarding secure information). However in a recent attempt to install a solution at our customer's site, I learned more about computer security than I have at any other time. </p> <p> Our customer, a well known corporation whom I will call ACME for anonymity, is in custody of sensitive information. Product movement data, financial data, and demographic data are all stored in one of a couple of huge server farms. Our application was to reside in the De-Militarized Zone (DMZ), and talk to a database behind the firewall. When they discovered that the application server we chose required Remote Procedure Calls (the subject of many CERT advisories in the Unix world), we hit a brick wall. Our application was no longer trusted, and was not to be installed. Luckily the next version of the application server fixed that problem. </p> <p> In the midst of this, I decided to learn as much as I could about operating in a hardened environment. Hardening involves turning off access to anything that is not needed, and only allowing what is needed. All mail servers, ftp servers, rpc services, telnet, and any other clear text communications ports need to be removed. All communication into and out of the box needs to be encrypted, with the exception of HTTP (although we were using HTTPS). </p> <p> All of this was necessary. I understand the principles behind it. However, I decided to ask their security analyst how to learn more--so we don't run into this problem again. He gave me a link to <link href="http://www.sans.org">SANS institute</link> and a word of advice: "Be paranoid. Don't trust anything." </p> <p> There is a point where the aforementioned philosophy goes a bit too far. The case in point relates to a story I heard working with the DoD. During the height of the "Cold War" between the US and Russia, a US commanding officer required that all the computers be placed on these huge power conditioners to reduce the Electro-Magnetic Interference (EMI) coming from the power line feedback of the computers. His rationalization was that he was positive KGB agents had the technology that they could read the EMI interference on the power lines and read the bits on the computers. In hindsight this is improbable; no one can identify the bits travelling on a computer from EMI in the power lines due to the level of noise (clocks, addressing lines, <em>encrypted data</em>, and other computers on the network). </p> <p> The security industry has a general rule of thumb to ensure that you don't spend too much time in this area: The cost of cracking the server should be more than the information that is protected is worth. Basically it boils down to this: sites like Slashdot and SourceForge do not require as much security as a bank. Protecting free information is not as critical as protecting people's bank accounts. I am not minimizing the contributions of the aforementioned sites to the world as a whole, but people become much more agitated if their bank account is wiped clean than if their news article is defaced. This is not to say that if you are protecting free information then you can safely ignore security. While the information is monetarily free to customers, it has value that can be measured in pride, respect, and accountability. </p> <p> The moral of the story is be paranoid to a point. Avalon is designed to be a trusted system, and will be improved to work in an untrusted network. </p> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-ioc.xml Index: guide-patterns-ioc.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Inversion of Control</title> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> One of the key design principles behind Avalon is the principle of <em>Inversion of Control</em>. <em>Inversion of Control</em> is a concept promoted by one of the founders of the Avalon project, <link href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</link>. The principle enforces security by design. </p> <p> It is difficult to track down one paper that defines this pattern at length, so here are a couple of different definitions of <em>Inversion of Control</em>. </p> </section> <section> <title>What it Means</title> <p> The Framework plays the role of the main program in coordinating and sequencing events and application activity. </p> <p> A designer sets up a chain among objects that can all react to certain messages in a delegation hierarchy. There is one major semantic detail: Inversion of Control refers to a parent object <em>controlling</em> a child object. With this distinction, the SAX API is not considered Inversion of Control because its purpose is to send <em>information</em> from a source to a handler. </p> <section> <title>Definition by Analogy</title> <p> There are a couple of different analogies that make understanding <em>Inversion of Control</em> easier. We experience this in many different ways in regular life, so we are borrowing the form in code. One analogy is called the "Chain of Command" in the military. </p> <section> <title>Chain of Command</title> <p> This is probably the clearest parallel to <em>Inversion of Control</em>. The military provides each new recruit with the basic things he needs to operate at his rank, and issues commands that recruit must obey. The same principle applies in code. Each component is given the provisions it needs to operate by the instantiating entity (i.e. Commanding Officer in this analogy). The instantiating entity then acts on that component how it needs to act. </p> <p> There are some deficiencies in this analogy as some military or ex-military people have explained to me. In the military, <strong>any</strong> Commanding Officer can issue commands to anyone under his or her rank. In the development world, to ensure proper security, this is not a pattern you want in your software. In Avalon, Inversion of Control (IoC) is from one parent (controlling) object to a child (controlled) component. A parent may have many children, but children only have one parent. </p> </section> </section> </section> <section> <title>How to Apply It</title> <p> <em>Inversion of Control</em> is applied in a very simple manner. Basically, it means that the component architecture employs a <em>passive</em> structure. See the following code: </p> <source> class MyComponent implements LogEnabled { Logger logger; public enableLogging(Logger newLogger) { this.logger = newLogger; } myMethod() { logger.info("Hello World!"); } } </source> <p> The parent of MyComponent instantiates MyComponent, sets the Logger, and calls myMethod. The component is not autonomous, and is given a logger that has been configured by the parent. </p> <p> The MyComponent class has no state apart from the parent, and has no way of obtaining a reference to the logger implementation without the parent giving it the implementation it needs. </p> </section> <section> <title>IOC promotes Security</title> <p>A big advantage of IOC for server applications is that it promotes security. You can read an analysis about this <link href="guide-patterns-ioc-security.html"> here </link>.</p> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-soc.xml Index: guide-patterns-soc.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Multi Dimensional Separation of Concerns</title> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> The concept of using different points of view within the system goes a long way in the overall comprehension of the system. </p> <p>You can get more formal information in this paper: <link href="http://www.research.ibm.com/hyperspace/MDSOC.htm">Multi-Dimensional Separation of Concerns</link>. </p> <section> <title>What it Means</title> <p> "Separation of Concerns" in its simplest form is separating a problem into different points of view. For instance, the documentation uses the "Separation of Concerns" pattern to make the documents comprehensible (we have separate documents for developers, administrators, and block implementers). The documents also use the pattern with XML and XSL so that the look is separated from the content. Either can change without breaking the other. </p> <p> This pattern is less clear to point out in the code, however the concept is evident. There are several interfaces included in Avalon that identify an object's role within the system. For instance, all components have certain contracts -- therefore any object that implements the Component interface must comply with those contracts. This allows developers to manipulate components using a standard interface, without worrying about the semantics of the implementation. They are separate concerns. </p> </section> <section> <title>How to Use It</title> <p> There are many ways to separate concern areas, but in Avalon we use interfaces to define the concern areas addressed in code. </p> <p> Every time you use interfaces within Object Oriented Programming (OOP), you are using the "Separation of Concerns" Pattern. The interface separates the concern of the implementation from the concern of the user of the interface. For example, every object that can be configured implements the Configurable interface. The contract surrounding the Configurable interface is that the instantiator of the object passes a Configuration object to the Configurable object (see "Inversion of Control"). Just what the Configurable object does with the passed Configuration object is irrelevant to the instantiator. </p> </section> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-soii.xml Index: guide-patterns-soii.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Separation of Interface and Implementation</title> <authors> <person name="Paul Hammant" email="[EMAIL PROTECTED]"/> <person name="Peter Donald" email="peter at apache.org"/> </authors> </header> <body> <section> <title>Introduction</title> <p> The core concept of interface and implementation separation is built into Java itself in that it has interfaces and classes. Many toolkits have been developed along the lines of an API / implementation separation. One such toolkit is the SAX API and the multiple XML parsers that implement it. Developers are quite happy using Apache's Xerces via the SAX API and understand that SAX represents the interface and Xerces an implementation. We notice that a lot of developers are happy to use interface/impl separated tools, but not to make them. We will try to justify in this document why we think people making applications should define interface/impl boundaries early in the design cycle. </p> <section> <title>Justification</title> <p> The main reason we do it is because: </p> <ol> <li>it forces you to decouple different modules/components/objects</li> <li>if specified correctly allows you to easily change the implementation of the interface/contract in the future</li> <li>makes it possible for a user to read documentation about the interface without having the implementation details clutter up their perception</li> <li>increases the possibility of reuse in a larger application</li> </ol> <p> If you are building objects with the aim of reuse then [3] is important but most people don't build for reuse (and most XP advocates say you should just plan to use not reuse) and thus [1] and [2] are more important. If you feel like documenting that and expanding this then feel free to. </p> </section> <section> <title>Example</title> <p> Let us hope this is not necessary: </p> <source> package helloworld; public interface HelloWorld { void sayHello(String greeting); } package helloworld.impl.default; public class DefaultHelloWorld implements HelloWorld { void sayHello(String greeting) { System.out.println("HelloWorld Greeting: " + greeting); } } package helloworld.impl.remote; public class RemoteHelloWorld implements HelloWorld { private RemoteMessager mRemoteMessager; public RemoteHelloWorld(RemoteMessager rm) { RemoteMessager = rm; } void sayHello(String greeting) { rm.sendMessage("HelloWorld Greeting: " + greeting); } } </source> </section> <section> <title>History</title> <p> We are referring to this pattern as <strong>interface/impl separation</strong>. Wiley's Patterns in Java book refers to it simply as 'Interface', but we feel that the word interface is overloaded enough in English and computing. </p> <p> It might be true to say that this is 'API/implementation separation', but this too could be confusing as the aforementioned SAX is not quite a pure set of interfaces. It has a static factory that thunks in an implementation that all subsequent calls to the factory method will be forced to use. See Anti-Patterns below. </p> <p> Better might be 'separation of implementation and the interface/contract' as that is quite correct, but a tad unwieldy. </p> </section> </section> <section> <title>Related Topics</title> <section> <title>Implementation Hiding</title> <p> Once a tool is split into interface and impl, it is possible for a container to hide the implementation. Most containers already use dynamic proxys (available in the JDK since 1.3), but we are talking about having the classes of the implementation hidden from classes using the interface. </p> <p> To do this, it is easiest to mount the impl classes in a separate classloader to the classloader that the interface-using classes are mounted in. The interfaces being mounted in a classloader that is visible to both. </p> <p> This is not a new proposition. Sun defined the servlet spec, and included rules about implementation hiding for hosted servlets. Essentially, instantiated servlets are only allowed to 'see' classes from the JDK, their own WAR file and those of the Servlet API itself. Tomcat correctly hides the implementation of the Servlet API from the hosted servlets. </p> <p> To actually achieve this separation, many containers (including those from the Avalon project) require that the interface and impl are in separate jars. Or to put it another way, there is no point separating your interface and impl classes if you are going to distribute them in the same jar. </p> </section> <section> <title>Kernel, Client API, Hosted Components</title> <p> This is building on the previous section, and in short is referred to as K/CAPI/HC. Basically the kernel mounts hosted components and satisfies their need for a client API. However the kernel wants to hide its implementation from the hosted components. </p> <p> An EJB container is another good example of this. EntityBean, SessionBean etc. is the client API. The hosted components are the beans, and the container has a kernel. It builds a complex tree of classloaders to separate its implementation, the client API, the JDK's runtime jar (that always being in the system or primordial classloader), and the hosted components. </p> <p> The central message of this is that if you have interface/impl separated your tool, and are doing tricky things with more classloaders in the implementation, please make sure you do not assume that the parent classloader of any classloader is the system classloader. If your reusable tool has been taken by another team and at some non root place in a classloader tree, then the tools will fail if you have made such assumptions. </p> </section> <section> <title>Anti-Patterns</title> <p> SAX, mentioned in multiple contexts in this document, is also an example of where the design can go wrong. The Factory is static (that in itself is an anti-pattern to IoC). Despite giving the appearance of having the ability to generate a parser based on the implementation's class name, only the first caller of that method will register a parser for the whole environment to use. </p> <p> Given that the SAX API is now in the JDK, the environment we allude to above is the whole JVM. This is a problem because in a very complex application with differing concurrent needs for implementation of parsers, not all can be met if the SAX API is used for making parsers. </p> </section> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-patterns-what-are.xml Index: guide-patterns-what-are.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - What are Design Patterns?</title> <authors> <person name="Berin Loritsch" email="[EMAIL PROTECTED]"/> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Getting Started with Patterns</title> <p> I highly recommend reading the <link href="http://www6.software.ibm.com/developerworks/education/j-patterns/index.html"> "Java Design Patterns 101" </link> tutorial, and its follow-up <link href="http://www6.software.ibm.com/developerworks/education/j-patterns201/index.html"> "Java Design Patterns 201" </link>, if you are unfamiliar with the concept of design patterns (and see below for more information). Note that you have to register at the IBM DeveloperWorks site in order to read these, but that's a good idea anyway. </p> </section> <section> <title>Where to Learn more</title> <p> You can find more information about patterns from the following links: </p> <ol> <li>Brian Foote's <link href="http://www.laputan.org/foote/papers.html">Pattern documents</link> </li> <li> <link href="http://www6.software.ibm.com/developerworks/education/j-patterns/index.html"> "Java Design Patterns 101" </link> at DeveloperWorks</li> <li> <link href="http://www6.software.ibm.com/developerworks/education/j-patterns201/index.html"> "Java Design Patterns 201" </link> at DeveloperWorks</li> <li> <link href="http://cseng.aw.com/book/0,3828,0201633612,00.html"> "Java Design Patterns: Elements of Reusable Object-Oriented Software" </link> by the GoF (printed book)</li> </ol> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/guide-where-to-go-from-here.xml Index: guide-where-to-go-from-here.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Guide - Where to Go next</title> <authors> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>There's a lot more to study</title> <p> Each of the pages in this short guide deserves an entire book, and indeed, most of them have a lot of documentation devoted to them. Here we provide you with pointers where else to look for more information, within and outside of Avalon. </p> </section> <section> <title>Creating Components</title> <p> After all the information in this guide has sunk in, you're probably itching to write an Avalon component. Our <link href="http://avalon.apache.org/developing/index.html">Developing with Avalon guide </link> takes you through doing just that. You can download it as a PDF and read at your leisure (it comes down to 56 printed pages). If that's too much for you, we suggest you get the latest <link href="http://avalon.apache.org/excalibur/index.html">Excalibur</link> release and take those components as an example. One application that uses a lot of those components and is in widespread daily use is <link href="http://xml.apache.org/cocoon">Cocoon</link>. </p> </section> </body> </document> 1.21 +77 -111 jakarta-avalon/src/xdocs/index.xml 1.1 jakarta-avalon/src/xdocs/reference-containers.xml Index: reference-containers.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - Containers</title> <authors> <person id="PH" name="Paul Hammant" email="[EMAIL PROTECTED]"/> <person name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> There are various containers that are aware of the Avalon Framework interfaces. This is a sort-of comprehensive list. </p> </section> <section> <title>Standalone Containers</title> <p> These typically run from the command line and are launched via a legacy main() method. </p> <section> <title>Avalon Phoenix</title> <p> This is a sister project to Avalon Framework. It provides an environment for launching multiple, isolated, more or less unrestricted server applications as hosted components. These can be applications like a web server, RDBMS or EJB server. It provides many advanced features like automatic management, at the cost of a bit of complexity. See <link href="http://avalon.apache.org/phoenix/index.html">Phoenix</link>. </p> <p> Phoenix is the oldest of the Avalon Containers; it is probably the most powerful and most widely used. While still in alpha, this hints at the fact that we find it to be not completely future complete, rather than an infantile project. </p> </section> <section> <title>Avalon Excalibur's Tweety</title> <p> Tweety is almost the opposite of Phoenix. It is a recent development and written exclusively as a teaching tool. It has no features whatsoever besides basic support for the Avalon lifecycle. This results in a complete distribution the size of the Phoenix bootstrapper. See <link href="http://avalon.apache.org/excalibur/tweety">Tweety</link> </p> </section> <section> <title>Myrmidon</title> <p> Myrmidon is a proposal for the kernel of <link href="http://jakarta.apache.org/ant">Apache Ant</link> 2. See <link href="http://cvs.apache.org/viewcvs.cgi/jakarta-ant/proposal/myrmidon/">Myrmidon</link> </p> </section> </section> <section> <title>Embedded Containers</title> <p> These run inside another application (like a servlet engine) and are controlled by it. </p> <section> <title>Excalibur Component Manager</title> <p> This is used by various applications like Cocoon. Cocoon is run inside the Sun specified servlet context of a web-app. It is designed for such servlet-context reuse. ECM is the most stable of the containers (it is the only one with a stable release); it is also arguably the worst design. See <link href="http://avalon.apache.org/excalibur/component/">ECM</link>. </p> </section> <section> <title>Fortress</title> <p> Fortress is meant as a future replacement of ECM. It fixes several of ECMs flaws like a mixup of concerns. It is built to be very extensible, and it includes support for custom lifecycle extensions. Fortress is still pre-alpha. See <link href="http://avalon.apache.org/excalibur/fortress/">Fortress</link>. </p> </section> <section> <title>Merlin</title> <p> Another recent development is Merlin, which has a client API very similar to Phoenix (applications that can run within phoenix can run within merlin as well). Merlin is still pre-alpha. </p> <p> See <link href="http://home.osm.net/doc/merlin/index.html">Merlin</link>. </p> </section> <section> <title>Plexus</title> <p> Plexus is a container under development that will become the basis of the services framework for a sister project to Avalon, <link href="http://jakarta.apache.org/turbine">Turbine</link>. </p> <p> See <link href="http://tambora.zenplex.org/cgi-bin/cvsweb.cgi/plexus/">Plexus</link>. </p> <note> Plexus is being developed outside of Avalon itself as an external project. </note> </section> <section> <title>Enterprise Object Broker (EOB)</title> <p> The reference implementation of this EJB-replacement container runs on top of Phoenix. EOB supports a subset of the Avalon Framework interfaces but allows RPC publishing of arbitary interfaces apparent in a hosted components object model. </p> <p> See <link href="http://eob.sourceforge.net/">EOB</link>. </p> <note> EOB is an being developed outside of Avalon itself as an external project. </note> </section> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/reference-the-lifecycle.xml Index: reference-the-lifecycle.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd"> <document> <header> <title>Avalon Framework - The Component Lifecycle</title> <authors> <person id="BL" name="Berin Loritsch" email="[EMAIL PROTECTED]"/> <person id="PD" name="Peter Donald" email="peter at apache.org"/> <person id="LS" name="Leo Simons" email="[EMAIL PROTECTED]"/> </authors> </header> <body> <section> <title>Introduction</title> <p> A component lives within something called a container. The contract between a container and a contained component is simple: the container is required to take a component through what is called its <strong>lifecycle</strong>. </p> <p> The Avalon project provides an application that functions as a container for componentized applications called <link href="http://avalon.apache.org/phoenix/index.html">Phoenix</link>. This is not exclusive, components adhering to lifecycle interfaces, can be mounted in custom containers. Cocoon and others mounts their own containers for components and invoke relevant methods from the lifecycle interfaces. See <link href="reference-containers.html">Containers</link>. </p> <p> The lifecyle methods from the Avalon Framework sub-project are designed to be used by just about any component hosted by any container. Of course, the API in question may well require additional interfaces for strongly typed functionality, but these interfaces should negate the need for any duplication of effort. </p> </section> <section> <title>The Lifecycle</title> <p> The lifecycle of a component specifies the methods that can be called on it, and the order in which this may happen. Some methods can be called only once in a specific <code>phase</code> of a component's lifecycle, others may be called multiple times. These methods are called the lifecycle methods. </p> <p> It is up to each container to indicate which lifecycle methods it will honor. This should be clearly documented together with the description of the container. A sister project to Phoenix supports all of the lifecycle methods defined in the Avalon Framework API. </p> </section> <section> <title>The Lifecycle Interfaces</title> <p> A component exposes its lifecycle methods by implementing the lifecycle interfaces. Each of these defines one or more methods that represent a specific phase in a component's lifecycle. The defined interfaces are: </p> <ol> <li>LogEnabled</li> <li>Contextualizable</li> <li>Serviceable (replacement for Composable)</li> <li>Configurable</li> <li>Parameterizable</li> <li>Initializable</li> <li>Startable</li> <li>Suspendable</li> <li>Recontextualizable</li> <li>Recomposable</li> <li>Reconfigurable</li> <li>Reparameterizable</li> <li>Stoppable</li> <li>Disposable</li> </ol> <note> <strong>Note:</strong>java.lang.Runnable has also been in use as a lifecycle interface. This is not recommended and is not supported by Avalon. Instead, the run() method is the responsibility of the component itself. If you wish to use it, call it from within start() or another method. </note> </section> <section> <title>Phase Order</title> <p> The order in which the various lifecycle methods are called is very specific. While none are required (it is possible to have a component implementing none of the lifecycle methods, although the use of that would be limited), some can only be used when others are as well. This is best explained using a few examples. </p> <section> <title>Simple Examples</title> <p>The lifecycle of a component implementing only Configurable for example will be:</p> <ol> <li>constructor</li> <li>configure</li> <li>finalize</li> </ol> <p>The lifecycle of a component implementing only Serviceable will be:</p> <ol> <li>constructor</li> <li>service</li> <li>finalize</li> </ol> </section> <section> <title>Complete</title> <p> If a component implements more than one interface the order of the events (service, configure etc.) follow a specific order. A component implementing all above interfaces (including Runnable) will follow these specific paths. </p> <p> Startup Phase: </p> <ol> <li>constructor <strong>as a consequence of instantiation</strong> </li> <li>contextualize</li> <li>service or compose</li> <li>configure</li> <li>parameterize</li> <li>initialize</li> <li>start</li> </ol> <p> At various or repeated times after startup: </p> <ol> <li>suspend</li> <li>recontextualize</li> <li>recompose</li> <li>reconfigure</li> <li>reparameterize</li> <li>resume</li> </ol> <p> Shutdown Phase: </p> <ol> <li>stop</li> <li>dispose</li> <li>finalize <strong>at some indeterminate moment by the garbage collector</strong> </li> </ol> </section> <section> <title>Phases executed once</title> <p> These lifecycle methods are only called once in the entire life of a component: </p> <ul> <li>contextualize</li> <li>service</li> <li>configure</li> <li>parameterize</li> <li>initialize</li> <li>dispose</li> </ul> </section> <section> <title>Phases executed once or more</title> <p> These lifecycle methods are called at least once and possibly more, depending on the container: </p> <ul> <li>start</li> <li>stop</li> </ul> </section> <section> <title>The Suspendable Interface</title> <p> The methods suspend() and resume() are not guaranteed to be called at all, even when implemented. They can be called more than once, but only after one another and between start() and stop(). The reason they exist is so the container can notify the component it needs to temporarily stop any operations. The container may need to perform some synchronized operation on one of the components used by this component, or it may wish to call any of the following methods, which can also be called zero or more times, and only between a suspend() and a resume(). </p> <ul> <li>recontextualize()</li> <li>recompose()</li> <li>reconfigure()</li> <li>reparameterize()</li> </ul> </section> </section> </body> </document> 1.1 jakarta-avalon/src/xdocs/tabs.xml Index: tabs.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE tabs PUBLIC "-//APACHE//DTD Cocoon Documentation Tab V1.0//EN" "tab-cocoon-v10.dtd"> <tabs software="MyProj" title="MyProj" copyright="Foo" xmlns:xlink="http://www.w3.org/1999/xlink"> <tab label="Avalon Home" href="http://avalon.apache.org/"/> <tab label="Framework" dir=""/> <tab label="Components" href="http://avalon.apache.org/components/"/> <tab label="Phoenix" href="http://avalon.apache.org/phoenix/"/> <tab label="SECA" href="http://avalon.apache.org/seca/"/> <tab label="Apps" href="http://avalon.apache.org/apps/"/> </tabs>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]