river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r780791 [17/17] - in /websites/staging/river/trunk/content/river/specs: ./ html/ html/images/
Date Thu, 16 Dec 2010 16:02:59 GMT
Added: websites/staging/river/trunk/content/river/specs/html/standard.css
==============================================================================
--- websites/staging/river/trunk/content/river/specs/html/standard.css (added)
+++ websites/staging/river/trunk/content/river/specs/html/standard.css Thu Dec 16 16:02:58 2010
@@ -0,0 +1,52 @@
+/* Document Defaults */
+body { font-size: 10pt; font-style: normal; font-weight: normal; color: #000000; background-color: #FFFFFF; letter-spacing: normal; text-align: left; text-indent: 15pt; word-spacing: normal}
+a:active { color: #0000CC}
+a:hover { color: #CC0033}
+a:link { color: #3366CC}
+a:visited { color: #9999CC}
+
+/* Paragraph Styles */
+.Body { margin-left: 0pt}
+.BodyRelative { }
+.CellBody { }
+.CellHeading { text-align: center; font-weight: bold; color: #003366}
+.ChapNumber color:{ #ffffff}
 
+.GroupTitlesIX { font-size: 16pt; color: #003366}
+.Heading1 { text-align: center; font-size: 20pt; color: #003366 ; font-weight: bold; margin-top: 20px}
+.Heading1A { font-size: 20pt; font-weight: bold; color: #003366 ; margin-top: 20px}
+.Heading2 { font-size: 15pt; font-weight: bold; color: #003366}
+.Heading3 { font-size: 12pt; font-weight: bold; color: #003366}
+.Heading4 { font-size: 12pt; font-weight: bold; font-style: italic; color: #003366}
+.Indented1 { }
+.Indented2 { }
+.Indented3 { }
+.Indented4 { }
+.IndentedRelative { }
+.Level1IX { }
+.Level12IX { }
+.Level13IX { }
+.NewHtmlPage { text-align: center; font-size: 18pt; color: #003366 ; font-weight: bold; margin-top: 20px}
+.Preformatted { margin-left: 30pt}
+.PreformattedRelative { }
+.SmartList1 { }
+.SmartList2 { }
+.SmartList3 { }
+.SmartList4 { }
+.TableTitle { text-align: center; font-style: italic; font-weight: bold}
+.Title { text-align: center; font-size: 18pt; color: #003366; font-weight: bold; margin-top: 20px}
+.TOC1 {  font-size: 13pt; font-weight: bold}
+.TOC2 {  font-size: 11pt}
+.TOC3 {  font-size: 10pt}
+.TOC4 {  font-size: 9pt}
+
+/* Character Styles */
+.Code { font-family: Lucida Sans Typewriter, sans-serif;}
+.CodeEmphasis { font-style: italic}
+.CodeStrong { font-weight: bold}
+.Emphasis { font-style: italic}
+.EmphasisUnderline { font-style: italic; text-decoration: underline}
+.Strong { font-weight: bold}
+.StrongUnderline { font-weight: bold; text-decoration: underline}
+.SubScript { }
+.SuperScript { }
+.WebJump { }

Added: websites/staging/river/trunk/content/river/specs/html/txn-spec.html
==============================================================================
--- websites/staging/river/trunk/content/river/specs/html/txn-spec.html (added)
+++ websites/staging/river/trunk/content/river/specs/html/txn-spec.html Thu Dec 16 16:02:58 2010
@@ -0,0 +1,935 @@
+<!--
+ ! Licensed to the Apache Software Foundation (ASF) under one
+ ! or more contributor license agreements.  See the NOTICE file
+ ! distributed with this work for additional information
+ ! regarding copyright ownership. The ASF licenses this file
+ ! to you under the Apache License, Version 2.0 (the
+ ! "License"); you may not use this file except in compliance
+ ! with the License. You may obtain a copy of the License at
+ ! 
+ !      http://www.apache.org/licenses/LICENSE-2.0
+ ! 
+ ! Unless required by applicable law or agreed to in writing, software
+ ! distributed under the License is distributed on an "AS IS" BASIS,
+ ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ! See the License for the specific language governing permissions and
+ ! limitations under the License.
+ !-->
+
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<meta name="GENERATOR" content="Quadralay WebWorks Publisher 5.0.4">
+<link rel="StyleSheet" href="standard.css" type="text/css" media="screen">
+<title>Jini Transaction Spec</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<a href="#skip" title="Skip navigation bar"></a>
+<table width="90%">
+<tr>
+<td align=left><a href="../../spec-index.html">Spec Index</a></td>
+<td align=right><em>Jini Technology Core Platform Specifications</em></td>
+</tr>
+</table>
+<br clear="all">
+
+
+<hr align="left">
+<table width="90%">
+<tr>
+<td align="right" font size="4"><b>Version 2.0</b></td>
+</tr>
+</table>
+<a name="skip"></a>
+<blockquote>
+<h2 align="left">TX - Jini<font size="-1"><sup>TM</sup></font> Transaction Specification<br>
+</h2>
+<h3 class="Heading2">
+  <a name="7127"> </a>TX.1	 Introduction	 
+</h3>
+<p class="Body">
+  Transactions are a fundamental tool for many kinds of computing. A transaction allows a set of operations to be grouped in such a way that they either all succeed or all fail; further, the operations in the set appear from outside the transaction to occur simultaneously. Transactional behaviors are especially important in distributed computing, where they provide a means for enforcing consistency over a set of operations on one or more remote participants. If all the participants are members of a transaction, one response to a remote failure is to abort the transaction, thereby ensuring that no partial results are written.
+</p>
+<p class="Body">
+  <a name="34911"> </a>Traditional transaction systems often center around transaction processing monitors that ensure that the correct implementation of transactional semantics is provided by all of the participants in a transaction. Our approach to transactional semantics is somewhat different. Within our system we leave it to the individual objects that take part in a transaction to implement the transactional semantics in the way that is best for that kind of object. What the system primarily provides is the coordination mechanism that those objects can use to communicate the information necessary for the set of objects to agree on the transaction. The goal of this system is to provide the <em class="Emphasis">minimal</em> set of protocols and interfaces that <em class="Emphasis">allow</em> objects to implement transaction semantics rather than the <em class="Emphasis">maximal</em> set of interfaces, protocols, and policies that <em class="Emphasis">ensure</em> the corre
 ctness of any possible transaction semantics. So the completion protocol is separate from the semantics of particular transactions.
+</p>
+<p class="Body">
+  <a name="34877"> </a>This document presents this completion protocol, which consists of a two-phase commit protocol for distributed transactions. The two-phase commit protocol defines the communication patterns that allow distributed objects and resources to wrap a set of operations in such a way that they appear to be a single operation. The protocol requires a manager that will enable consistent resolution of the operations by a guarantee that all participants will eventually know whether they should commit the operations (roll forward) or abort them (roll backward). A participant can be any object that supports the participant contract by implementing the appropriate interface. Participants are not limited to databases or other persistent storage services.
+</p>
+<p class="Body">
+  <a name="3222"> </a>Clients and servers will also need to depend on specific transaction semantics. The default transaction semantics for participants is also defined in this document.
+</p>
+<p class="Body">
+  <a name="34885"> </a>The two-phase commit protocol presented here, while common in many traditional transaction systems, has the potential to be used in more than just traditional transaction processing applications. Since the semantics of the individual operations and the mechanisms that are used to ensure various properties of the meta-operation joined by the protocol are left up to the individual objects, variations of the usual properties required by transaction processing systems are possible using this protocol, as long as those variances can be resolved by this protocol. A group of objects could use the protocol, for example, as part of a process allowing synchronization of data that have been allowed to drift for efficiency reasons. While this use is not generally considered to be a classical use of transactions, the protocol defined here could be used for this purpose. Some variations will not be possible under these protocols, requiring subinterfaces and subclass
 es of the ones provided or entirely new interfaces and classes.
+</p>
+<p class="Body">
+  <a name="2798"> </a>Because of the possibility of application to situations that are beyond the usual use of transactions, calling the two-phase commit protocol a transaction mechanism is somewhat misleading. However, since the most common use of such a protocol is in a transactional setting, and because we do define a particular set of default transaction semantics, we will follow the usual naming conventions used in such systems rather than attempting to invent a new, parallel vocabulary.
+</p>
+<p class="Body">
+  <a name="3577"> </a>The classes and interfaces defined by this specification are in the packages <code>net.jini.core.transaction</code> and <code>net.jini.core.transaction.server</code>. In this document you will usually see these types used without a package prefix; as each type is defined, the package it is in is specified.
+</p>
+<h4 class="Heading3">
+  <a name="1779"> </a>TX.1.1	 Model and Terms
+</h4>
+<p class="Body">
+  <a name="33159"> </a>A transaction is created and overseen by a <em class="Emphasis">manager.</em> Each manager implements the interface <code>TransactionManager</code>. Each <em class="Emphasis">transaction</em> is represented by a <code>long</code> identifier that is unique with respect to the transaction's manager.
+</p>
+<p class="Body">
+  <a name="34996"> </a>Semantics are represented by <em class="Emphasis">semantic</em> transaction objects, such as the ones that represent the default semantics for services. Even though the manager needs to know only how to complete transactions, clients and participants need to share a common view of the semantics of the transaction. Therefore clients typically create, pass, and operate on semantic objects that contain the transaction identifier instead of using the transaction's identifier directly, and transactable services typically accept parameters of a particular semantic type, such as the <code>Transaction</code> interface used for the default semantics.
+</p>
+<p class="Body">
+  <a name="35026"> </a>As shown in Figure TX.1.1, a <em class="Emphasis">client</em> asks the manager to create a transaction, typically by using a semantic factory class such as <code>TransactionFactory</code> to create a semantic object. The semantic object created is then passed as a parameter when performing operations on a service. If the service is to accept this transaction and govern its operations thereby, it must <em class="Emphasis">join</em> the transaction as a <em class="Emphasis">participant.</em> Participants in a transaction must implement the <code>TransactionParticipant</code> interface. Particular operations associated with a given transaction are said to be <em class="Emphasis">performed under</em> that transaction. The client that created the transaction might or might not be a participant in the transaction.
+<CENTER><p>
+<img src="images/txn-speca.gif" alt="This graphic illustrates the following few paragraphs." height="238" width="480">
+
+</p>
+<div style="color: #000000; font-family: Times; font-size: 11pt; font-style: italic; font-weight: bold; margin-bottom: 17pt; margin-left: 54pt; margin-right: 0pt; margin-top: 7pt; text-align: left; text-decoration: none; text-indent: -54pt; text-transform: none; vertical-align: baseline"></div>
+<a name="35064"> </a><B><I>Figure TX.1.1:	 Transaction Creation and Use</I></B><br>
+</div>
+</CENTER>
+<p class="Body">
+  <a name="33415"> </a>A transaction <em class="Emphasis">completes</em> when any entity either <em class="Emphasis">commits</em> or <em class="Emphasis">aborts</em> the transaction. If a transaction commits successfully, then all operations performed under that transaction will complete. Aborting a transaction means that all operations performed under that transaction will appear never to have happened.
+</p>
+<p class="Body">
+  <a name="33447"> </a>Committing a transaction requires each participant to <em class="Emphasis">vote,</em> where a vote is either <em class="Emphasis">prepared</em> (ready to commit), <em class="Emphasis">not changed</em> (read-only), or <em class="Emphasis">aborted</em> (the transaction should be aborted). If all participants vote "prepared" or "not changed," the transaction manager will tell each "prepared" participant to <em class="Emphasis">roll forward,</em> thus committing the changes. Participants that voted "not changed" need do nothing more. If the transaction is ever aborted, the participants are told to <em class="Emphasis">roll back</em> any changes made under the transaction.
+</p>
+<h4 class="Heading3">
+  <a name="33449"> </a>TX.1.2	 Distributed Transactions and ACID Properties
+</h4>
+<p class="Body">
+  <a name="2733"> </a>The two-phase commit protocol is designed to enable objects to provide <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties. The default transaction semantics define one way to preserve these properties. The <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties are:
+</p>
+<ul>
+  <li class="SmartList1"><a name="2734"> </a><em class="Emphasis">Atomicity:</em> All the operations grouped under a transaction occur or none of them do. The protocol allows participants to discover which of these alternatives is expected by the other participants in the protocol. However, it is up to the individual object to determine whether it wishes to operate in concert with the other participants.<p>
+  <li class="SmartList1"><a name="35529"> </a><em class="Emphasis">Consistency:</em> The completion of a transaction must leave the system in a consistent state. Consistency includes issues known only to humans, such as that an employee should always have a manager. The enforcement of consistency is outside of the realm of the transaction itself--a transaction is a tool to allow consistency guarantees and not itself a guarantor of consistency.<p>
+  <li class="SmartList1"><a name="2736"> </a><em class="Emphasis">Isolation:</em> Ongoing transactions should not affect each other. Participants in a transaction should see only intermediate states resulting from the operations of their own transaction, not the intermediate states of other transactions. The protocol allows participating objects to know what operations are being done within the scope of a transaction. However, it is up to the individual object to determine if such operations are to be reflected only within the scope of the transaction or can be seen by others who are not participating in the transaction.<p>
+  <li class="SmartList1"><a name="2737"> </a><em class="Emphasis">Durability:</em> The results of a transaction should be as persistent as the entity on which the transaction commits. However, such guarantees are up to the implementation of the object.
+</ul>
+<p class="Body">
+  <a name="34891"> </a>The dependency on the participant's implementation for the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties is the greatest difference between this two-phase commit protocol and more traditional transaction processing systems. Such systems attempt to ensure that the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties are met and go to considerable trouble to ensure that no participant can violate any of the properties.
+</p>
+<p class="Body">
+  <a name="35154"> </a>This approach differs for both philosophical and practical reasons. The philosophical reason is centered on a basic tenet of object-oriented programming, which is that the implementation of an object should be hidden from any part of the system outside the object. Ensuring the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties generally requires that an object's implementation correspond to certain patterns. We believe that if these properties are needed, the object (or, more precisely, the programmer implementing the object) will know best how to guarantee the properties. For this reason, the manager is solely concerned with completing transactions properly. Clients and participants must agree on semantics separately.
+</p>
+<p class="Body">
+  <a name="3270"> </a>The practical reason for leaving the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties up to the object is that there are situations in which only some of the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties make sense, but that can still make use of the two-phase commit protocol. A group of transient objects might wish to group a set of operations in such a way that they appear atomic; in such a situation it makes little sense to require that the operations be durable. An object might want to enable the monitoring of the state of some long-running transactions; such monitoring would violate the isolation requirement of the <span style="color: #000000; font-size: 10pt; font-style: normal; font-w
 eight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties. Binding the two-phase commit protocol to all of these properties limits the use of such a protocol.
+</p>
+<p class="Body">
+  <a name="3273"> </a>We also know that particular semantics are needed for particular services. The default transaction semantics provide useful general-purpose semantics built on the two-phase commit completion protocol.
+</p>
+<p class="Body">
+  <a name="3271"> </a>Distributed transactions differ from single-system transactions in the same way that distributed computing differs from single-system computing. The clearest difference is that a single system can have a single view of the state of several services. It is possible in a single system to make it appear to any observer that all operations performed under a transaction have occurred or none have, thereby achieving isolation. In other words, no observer will ever see only part of the changes made under the transaction. In a distributed system it is possible for a client using two servers to see the committed state of a transaction in one server and the pre-committed state of the same transaction in another server. This can be prevented only by coordination with the transaction manager or the client that committed the transaction. Coordination between clients is outside the scope of this specification.
+</p>
+<h4 class="Heading3">
+  <a name="2697"> </a>TX.1.3	 Requirements
+</h4>
+<p class="Body">
+  <a name="2700"> </a>The transaction system has the following requirements:
+</p>
+<ul>
+  <li class="SmartList1"><a name="2705"> </a>Define types and contracts that allow the two-phase commit protocol to govern operations on multiple servers of differing types or implementations.<p>
+  <li class="SmartList1"><a name="2710"> </a>Allow participation in the two-phase commit protocol by any object in the Java<font size="-1"><sup>TM</sup></font> programming language, where "participation" means to perform operations on that object under a given transaction.<p>
+  <li class="SmartList1"><a name="2716"> </a>Each participant may provide <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties with respect to that participant to observers operating under a given transaction.<p>
+  <li class="SmartList1"><a name="2713"> </a>Use standard Java programming language techniques and tools to accomplish these goals. Specifically, transactions will rely upon Java Remote Method Invocation (<span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">Java RMI</span>) semantics to communicate between participants.<p>
+  <li class="SmartList1"><a name="3276"> </a>Define specific default transaction semantics for use by services.
+</ul>
+<h3 class="Heading2">
+  <a name="7130"> </a>TX.2	 The Two-Phase Commit Protocol	 
+</h3>
+<p class="Body">
+  The two-phase commit protocol is defined using three primary types:
+</p>
+<ul>
+  <li class="SmartList1"><a name="7133"> </a><code>TransactionManager</code>: A transaction manager creates new transactions and coordinates the activities of the participants.<p>
+  <li class="SmartList1"><a name="7134"> </a><code>NestableTransactionManager</code>: Some transaction managers are capable of supporting nested transactions.<p>
+  <li class="SmartList1"><a name="34287"> </a><code>TransactionParticipant</code>: When an operation is performed under a transaction, the participant must join the transaction, providing the manager with a reference to a <code>TransactionParticipant</code> object that will be asked to vote, roll forward, or roll back.
+</ul>
+<p class="Body">
+  <a name="35372"> </a>The following types are imported from other packages and are referenced in unqualified form in the rest of this specification:
+<pre  class="Preformatted">java.rmi.Remote
+java.rmi.RemoteException
+java.rmi.NoSuchObjectException
+java.io.Serializable
+net.jini.core.lease.LeaseDeniedException
+net.jini.core.lease.Lease
+</pre>
+<p class="Body">
+  <a name="35375"> </a>All the methods defined to throw <code>RemoteException</code> will do so in the circumstances described by the Java RMI specification.
+</p>
+<p class="Body">
+  <a name="7137"> </a>Each type is defined where it is first described. Each method is described where it occurs in the lifecycle of the two-phase commit protocol. All methods, fields, and exceptions that can occur during the lifecycle of the protocol will be specified. The section in which each method or field is specified is shown in a comment, using the &#167; abbreviation for the word "section."
+</p>
+<h4 class="Heading3">
+  <a name="7139"> </a>TX.2.1	 Starting a Transaction
+</h4>
+<p class="Body">
+  <a name="7140"> </a>The <code>TransactionManager</code> interface is implemented by servers that manage the two-phase commit protocol:
+</p>
+<pre  class="Preformatted">package net.jini.core.transaction.server;
+
+public interface TransactionManager 
+    extends Remote, TransactionConstants<a href="txn-spec.html#7219"> // &#167;TX.2.4</a>
+{
+    public static class Created implements Serializable {
+        public final long id;
+        public final Lease lease;
+        public Created(long id, Lease lease) {...}
+    }
+    Created create(long leaseFor)<a href="txn-spec.html#7139"> // &#167;TX.2.1</a>
+        throws LeaseDeniedException, RemoteException;
+    void join(long id, TransactionParticipant part,
+              long crashCount)<a href="txn-spec.html#7194"> // &#167;TX.2.3</a>
+        throws UnknownTransactionException,
+               CannotJoinException, CrashCountException,
+               RemoteException;
+    int getState(long id)<a href="txn-spec.html#7341"> // &#167;TX.2.7</a>
+        throws UnknownTransactionException, RemoteException;
+    void commit(long id)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,                 
+               CannotCommitException,
+               RemoteException;
+    void commit(long id, long waitFor)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotCommitException,
+               TimeoutExpiredException, RemoteException;
+    void abort(long id)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotAbortException,
+               RemoteException;
+    void abort(long id, long waitFor)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotAbortException,
+               TimeoutExpiredException, RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="10530"> </a>A client obtains a reference to a <code>TransactionManager</code> object via a lookup service or some other means. The details of obtaining such a reference are outside the scope of this specification.
+</p>
+<p class="Body">
+  <a name="7170"> </a>A client creates a new transaction by invoking the manager's <code>create</code> method, providing a desired <code>leaseFor</code> time in milliseconds. This invocation is typically indirect via creating a semantic object. The time is the client's expectation of how long the transaction will last before it completes. The manager may grant a shorter lease or may deny the request by throwing <code>LeaseDeniedException</code>. If the granted lease expires or is cancelled before the transaction manager receives a <code>commit</code> or <code>abort</code> of the transaction, the manager will abort the transaction.
+</p>
+<p class="Body">
+  <a name="7171"> </a>The purpose of the <code>Created</code> nested class is to allow the <code>create</code> method to return two values: the transaction identifier and the granted lease. The constructor simply sets the two fields from its parameters.
+</p>
+<h4 class="Heading3">
+  <a name="33456"> </a>TX.2.2	 Starting a Nested Transaction
+</h4>
+<p class="Body">
+  <a name="35206"> </a>The <code>TransactionManager.create</code> method returns a new <em class="Emphasis">top-level</em> transaction. Managers that implement just the <code>TransactionManager</code> interface support only top-level transactions. <em class="Emphasis">Nested</em> transactions, also known as <em class="Emphasis">subtransactions</em>, can be created using managers that implement the <code>NestableTransactionManager</code> interface:
+<pre  class="Preformatted">package net.jini.core.transaction.server;
+
+public interface NestableTransactionManager 
+    extends TransactionManager
+{
+    TransactionManager.Created
+        create(NestableTransactionManager parentMgr,
+               long parentID, long leaseFor)<a href="txn-spec.html#33456"> // &#167;TX.2.2</a>
+        throws UnknownTransactionException,
+               CannotJoinException, LeaseDeniedException,
+               RemoteException;
+    void promote(long id, TransactionParticipant[] parts,
+                 long[] crashCounts,
+                 TransactionParticipant drop)
+        throws UnknownTransactionException, 
+               CannotJoinException, CrashCountException,
+               RemoteException;<a href="txn-spec.html#7341"> // &#167;TX.2.7</a>
+}
+</pre>
+<p class="Body">
+  <a name="33476"> </a>The <code>create</code> method takes a <em class="Emphasis">parent</em> transaction--represented by the manager for the parent transaction and the identifier for that transaction--and a desired lease time in milliseconds, and returns a new <em class="Emphasis">nested</em> transaction that is <em class="Emphasis">enclosed</em> <em class="Emphasis">by</em> the specified parent along with the granted lease.
+</p>
+<p class="Body">
+  <a name="7183"> </a>When you use a nested transaction you allow changes to a set of objects to abort without forcing an abort of the parent transaction, and you allow the commit of those changes to still be conditional on the commit of the parent transaction.
+</p>
+<p class="Body">
+  <a name="7184"> </a>When a nested transaction is created, its manager joins the parent transaction. When the two managers are different, this is done explicitly via <code>join</code> (see <a href="txn-spec.html#7194">Section TX.2.3 "Joining a Transaction"</a>). When the two managers are the same, this may be done in a manager-specific fashion.
+</p>
+<p class="Body">
+  <a name="7188"> </a>The <code>create</code> method throws <code>UnknownTransactionException</code> if the parent transaction is unknown to the parent transaction manager, either because the transaction ID is incorrect or because the transaction is no longer active and its state has been discarded by the manager.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class UnknownTransactionException
+    extends TransactionException
+{
+    public UnknownTransactionException() {...}
+    public UnknownTransactionException(String desc) {...}
+}
+
+public class TransactionException extends Exception {
+    public TransactionException() {...}
+    public TransactionException(String desc) {...}
+}
+</pre>
+<p class="Body">
+  <a name="7191"> </a>The <code>create</code> method throws <code>CannotJoinException</code> if the parent transaction is known to the manager but is no longer active.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class CannotJoinException extends TransactionException
+{
+    public CannotJoinException() {...}
+    public CannotJoinException(String desc) {...}
+}
+</pre>
+<h4 class="Heading3">
+  <a name="7194"> </a>TX.2.3	 Joining a Transaction
+</h4>
+<p class="Body">
+  <a name="7195"> </a>The first time a client tells a participant to perform an operation under a given transaction, the participant must invoke the transaction manager's <code>join</code> method with an object that implements the <code>TransactionParticipant</code> interface. This object will be used by the manager to communicate with the participant about the transaction.
+<pre  class="Preformatted">package net.jini.core.transaction.server;  
+
+public interface TransactionParticipant 
+    extends Remote, TransactionConstants<a href="txn-spec.html#7219"> // &#167;TX.2.4</a>
+{
+    int prepare(TransactionManager mgr, long id)<a href="txn-spec.html#7272"> // &#167;TX.2.6</a>
+        throws UnknownTransactionException, RemoteException;
+    void commit(TransactionManager mgr, long id)<a href="txn-spec.html#7272"> // &#167;TX.2.6</a>
+        throws UnknownTransactionException, RemoteException;
+    void abort(TransactionManager mgr, long id)<a href="txn-spec.html#7272"> // &#167;TX.2.6</a>
+        throws UnknownTransactionException, RemoteException;
+    int prepareAndCommit(TransactionManager mgr, long id)
+                                               <a href="txn-spec.html#7341"> // &#167;TX.2.7</a>
+        throws UnknownTransactionException, RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="33482"> </a>If the participant's invocation of the <code>join</code> method throws <code>RemoteException</code>, the participant should not perform the operation requested by the client and should rethrow the exception or otherwise signal failure to the client.
+</p>
+<p class="Body">
+  <a name="35231"> </a>The <code>join</code> method's third parameter is a <em class="Emphasis">crash count</em> that uniquely defines the version of the participant's storage that holds the state of the transaction. Each time the participant loses the state of that storage (because of a system crash if the storage is volatile, for example) it must change this count. 
+</p>
+<p class="Body">
+  <a name="35232"> </a>When a manager receives a <code>join</code> request, it checks to see if the participant has already joined the transaction. If it has, and the crash count is the same as the one specified in the original <code>join</code>, the <code>join</code> is accepted but is otherwise ignored. If the crash count is different, the manager throws <code>CrashCountException</code> and forces the transaction to abort.
+<pre  class="Preformatted">package net.jini.core.transaction.server;
+
+public class CrashCountException extends TransactionException
+{
+    public CrashCountException() {...}
+    public CrashCountException(String desc) {...}
+}
+</pre>
+<p class="Body">
+  <a name="7216"> </a>The participant should reflect this exception back to the client. This check makes <code>join</code> idempotent when it should be, but forces an abort for a second <code>join</code> of a transaction by a participant that has no knowledge of the first <code>join</code> and hence has lost whatever changes were made after the first <code>join</code>.
+</p>
+<p class="Body">
+  <a name="7217"> </a>An invocation of <code>join</code> can throw <code>UnknownTransactionException</code>, which means the transaction is unknown to the manager, either because the transaction ID was incorrect, or because the transaction is no longer active and its state has been discarded by the manager. The <code>join</code> method throws <code>CannotJoinException</code> if the transaction is known to the manager but is no longer active. In either case the <code>join</code> has failed, and the method that was attempted under the transaction should reflect the exception back to the client. This is also the proper response if <code>join</code> throws a <code>NoSuchObjectException</code>.
+</p>
+<h4 class="Heading3">
+  <a name="7219"> </a>TX.2.4	 Transaction States
+</h4>
+<p class="Body">
+  <a name="7220"> </a>The <code>TransactionConstants</code> interface defines constants used in the communication between managers and participants.
+<pre  class="Preformatted">package net.jini.core.transaction.server;
+
+public interface TransactionConstants {
+    	 int ACTIVE = 1;
+    	 int VOTING = 2;
+    	 int PREPARED = 3;
+    	 int NOTCHANGED = 4;
+    	 int COMMITTED = 5;
+    	 int ABORTED = 6;
+}
+</pre>
+<p class="Body">
+  <a name="7222"> </a>These correspond to the states and votes that participants and managers go through during the lifecycle of a given transaction.
+</p>
+<h4 class="Heading3">
+  <a name="7224"> </a>TX.2.5	 Completing a Transaction: The Client's View
+</h4>
+<p class="Body">
+  <a name="7262"> </a>In the client's view, a transaction goes through the following states:
+<p>
+<CENTER>
+<img src="images/txn-spec2.gif" alt="This graphic illustrates the following few paragraphs." height="202" width="480">
+</CENTER></p>
+<p class="Body">
+  <a name="7263"> </a>For the client, the transaction starts out <code>ACTIVE</code> as soon as <code>create</code> returns. The client drives the transaction to completion by invoking <code>commit</code> or <code>abort</code> on the transaction manager, or by cancelling the lease or letting the lease expire (both of which are equivalent to an <code>abort</code>).
+</p>
+<p class="Body">
+  <a name="35253"> </a>The one-parameter <code>commit</code> method returns as soon as the transaction successfully reaches the <code>COMMITTED</code> state, or if the transaction is known to have previously reached that state due to an earlier <code>commit</code>. If the transaction reaches the <code>ABORTED</code> state, or is known to have previously reached that state due to an earlier <code>commit</code> or <code>abort</code>, then <code>commit</code> throws <code>CannotCommitException</code>.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class CannotCommitException
+    extends TransactionException
+{
+    public CannotCommitException() {...}
+    public CannotCommitException(String desc) {...}
+}
+</pre>
+<p class="Body">
+  <a name="7266"> </a>The one-parameter <code>abort</code> method returns as soon as the transaction successfully reaches the <code>ABORTED</code> state, or if the transaction is known to have previously reached that state due to an earlier <code>commit</code> or <code>abort</code>. If the transaction is known to have previously reached the <code>COMMITTED</code> state due to an earlier <code>commit</code>, then <code>abort</code> throws <code>CannotAbortException</code>.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class CannotAbortException extends TransactionException
+{
+    public CannotAbortException() {...}
+    public CannotAbortException(String desc) {...}
+}
+</pre>
+<p class="Body">
+  <a name="29980"> </a>Both <code>commit</code> and <code>abort</code> can throw <code>UnknownTransactionException</code>, which means the transaction is unknown to the manager. This may be because the transaction ID was incorrect, or because the transaction has proceeded to <em class="Emphasis">cleanup</em> due to an earlier commit or abort, and has been forgotten.
+</p>
+<p class="Body">
+  <a name="7269"> </a>Overloads of the <code>commit</code> and <code>abort</code> methods take an additional <code>waitFor</code> timeout parameter specified in milliseconds that tells the manager to wait until it has successfully notified all participants about the outcome of the transaction before the method returns. If the timeout expires before all participants have been notified, a <code>TimeoutExpiredException</code> will be thrown. If the timeout expires before the transaction reaches the <code>COMMITTED</code> or <code>ABORTED</code> state, the manager must wait until one of those states is reached before throwing the exception. The <code>committed</code> field in the exception is set to <code>true</code> if the transaction committed or to <code>false</code> if it aborted.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class TimeoutExpiredException extends
+             TransactionException 
+{
+    public boolean committed;
+    public TimeoutExpiredException(boolean committed) {...}
+    public TimeoutExpiredException(String desc, 
+                                   boolean committed) {...}
+}
+</pre>
+<h4 class="Heading3">
+  <a name="7272"> </a>TX.2.6	 Completing a Transaction: A Participant's View
+</h4>
+<p class="Body">
+  <a name="7312"> </a>In a participant's view, a transaction goes through the following states:
+<p>
+<CENTER>
+<img src="images/txn-spec3.gif" alt="This graphic illustrates the following few paragraphs." height="278" width="504">
+
+</CENTER></p>
+<p class="Body">
+  <a name="10543"> </a>For the participant, the transaction starts out <code>ACTIVE</code> as soon as <code>join</code> returns. Any operations attempted under a transaction are valid only if the participant has the transaction in the <code>ACTIVE</code> state. In any other state, a request to perform an operation under the transaction should fail, signaling the invoker appropriately.
+</p>
+<p class="Body">
+  <a name="7314"> </a>When the manager asks the participant to <code>prepare</code>, the participant is <code>VOTING</code> until it decides what to return. There are three possible return values for <code>prepare</code>:
+</p>
+<ul>
+  <li class="SmartList1"><a name="7315"> </a>The participant had no changes to its state made under the transaction--that is, for the participant the transaction was read-only. It should release any internal state associated with the transaction. It must signal this with a return of <code>NOTCHANGED</code>, effectively entering the <code>NOTCHANGED</code> state. As noted below, a well-behaved participant should stay in the <code>NOTCHANGED</code> state for some time to allow idempotentcy for <code>prepare</code>.<p>
+  <li class="SmartList1"><a name="7316"> </a>The participant had its state changed by operations performed under the transaction. It must attempt to prepare to roll those changes forward in the event of a future incoming <code>commit</code> invocation. When the participant has successfully prepared itself to roll forward (see <a href="txn-spec.html#7394">Section TX.2.8 "Crash Recovery"</a>), it must return <code>PREPARED</code>, thereby entering the <code>PREPARED</code> state.<p>
+  <li class="SmartList1"><a name="7320"> </a>The participant had its state changed by operations performed under the transaction but is unable to guarantee a future successful roll forward. It must signal this with a return of <code>ABORTED</code>, effectively entering the <code>ABORTED</code> state.
+</ul>
+<p class="Body">
+  <a name="7321"> </a>For top-level transactions, when a participant returns <code>PREPARED</code> it is stating that it is ready to roll the changes forward by saving the necessary record of the operations for a future <code>commit</code> call. The record of changes must be at least as durable as the overall state of the participant. The record must also be examined during recovery (see <a href="txn-spec.html#7394">Section TX.2.8 "Crash Recovery"</a>) to ensure that the participant rolls forward or rolls back as the manager dictates. The participant stays in the <code>PREPARED</code> state until it is told to <code>commit</code> or <code>abort</code>. It cannot, having returned <code>PREPARED</code>, drop the record except by following the "roll decision" described for crash recovery (see <a href="txn-spec.html#35649">Section TX.2.8.1 "The Roll Decision"</a>).
+</p>
+<p class="Body">
+  <a name="7328"> </a>For nested transactions, when a participant returns <code>PREPARED</code> it is stating that it is ready to roll the changes forward into the parent transaction. The record of changes must be as durable as the record of changes for the parent transaction.
+</p>
+<p class="Body">
+  <a name="7329"> </a>If a participant is currently executing an operation under a transaction when <code>prepare</code> is invoked for that transaction, the participant must either: wait until that operation is complete before returning from <code>prepare</code>; know that the operation is guaranteed to be read-only, and so will not affect its ability to prepare; or abort the transaction.
+</p>
+<p class="Body">
+  <a name="7330"> </a>If a participant has not received any communication on or about a transaction over an extended period, it may choose to invoke <code>getState</code> on the manager. If <code>getState</code> throws <code>UnknownTransactionException</code> or <code>NoSuchObjectException</code>, the participant may safely infer that the transaction has been aborted. If <code>getState</code> throws a <code>RemoteException</code> the participant may choose to believe that the manager has crashed and abort its state in the transaction--this is not to be done lightly, since the manager may save state across crashes, and transient network failures could cause a participant to drop out of an otherwise valid and committable transaction. A participant should drop out of a transaction only if the manager is unreachable over an extended period. However, in no case should a participant drop out of a transaction it has <code>PREPARED</code> but not yet rolled forward.
+</p>
+<p class="Body">
+  <a name="7331"> </a>If a participant has joined a nested transaction and it receives a <code>prepare</code> call for an enclosing transaction, the participant must complete the nested transaction, using <code>getState</code> on the manager to determine the proper type of completion.
+</p>
+<p class="Body">
+  <a name="7332"> </a>If a participant receives a <code>prepare</code> call for a transaction that is already in a post-<code>VOTING</code> state, the participant should simply respond with that state.
+</p>
+<p class="Body">
+  <a name="7333"> </a>If a participant receives a <code>prepare</code> call for a transaction that is unknown to it, it should throw <code>UnknownTransactionException</code>. This may happen if the participant has crashed and lost the state of a previously active transaction, or if a previous <code>NOTCHANGED</code> or <code>ABORTED</code> response was not received by the manager and the participant has since forgotten the transaction.
+</p>
+<p class="Body">
+  <a name="7334"> </a>Note that a return value of <code>NOTCHANGED</code> may not be idempotent. Should the participant return <code>NOTCHANGED</code> it may proceed directly to clean up its state. If the manager receives a <code>RemoteException</code> because of network failure, the manager will likely retry the <code>prepare</code>. At this point a participant that has dropped the information about the transaction will throw <code>UnknownTransactionException</code>, and the manager will be forced to abort. A well-behaved participant should stay in the <code>NOTCHANGED</code> state for a while to allow a retry of <code>prepare</code> to again return <code>NOTCHANGED</code>, thus keeping the transaction alive, although this is not strictly required. No matter what it voted, a well-behaved participant should also avoid exiting for a similar period of time in case the manager needs to re-invoke <code>prepare</code>.
+</p>
+<p class="Body">
+  <a name="7335"> </a>If a participant receives an <code>abort</code> call for a transaction, whether in the <code>ACTIVE</code>, <code>VOTING</code>, or <code>PREPARED</code> state, it should move to the <code>ABORTED</code> state and roll back all changes made under the transaction.
+</p>
+<p class="Body">
+  <a name="7336"> </a>If a participant receives a <code>commit</code> call for a <code>PREPARED</code> transaction, it should move to the <code>COMMITTED</code> state and roll forward all changes made under the transaction.
+</p>
+<p class="Body">
+  <a name="7337"> </a>The participant's implementation of <code>prepareAndCommit</code> must be equivalent to the following:
+<pre  class="Preformatted">public int prepareAndCommit(TransactionManager mgr, long id)
+    throws UnknownTransactionException, RemoteException
+{
+
+    if (outcome for id is already known) {
+        return that outcome;
+    }
+
+    int result = prepare(mgr, id);
+    if (result == PREPARED) {
+        commit(mgr, id);
+        result = COMMITTED;
+    }
+    return result;
+}
+</pre>
+<p class="Body">
+  <a name="7339"> </a>The participant can often implement <code>prepareAndCommit</code> much more efficiently than shown, but it must preserve the above semantics. The manager's use of this method is described in the next section.
+</p>
+<p class="Body">Note that a call to <code>prepareAndCommit</code> might not be idempotent. Once the participant moves to the <code>NOTCHANGED</code>, <code>ABORTED</code>, or <code>COMMITTED</code> state it may then proceed directly to <em>cleanup</em>. If the manager receives a <code>RemoteException</code> because of network failure, the manager will likely retry the <code>prepareAndCommit</code>. At this point a participant that has dropped the information about the transaction will throw <code>UnknownTransactionException</code>, and the manager will be unable to determine the outcome of the previous <code>prepareAndCommit</code> call. Although not strictly required, a well-behaved participant should remain in its current state for a while to allow for retries of <code>prepareAndCommit</code>. 
+<h4 class="Heading3">
+  <a name="7341"> </a>TX.2.7	 Completing a Transaction: The Manager's View
+</h4>
+<p class="Body">
+  <a name="7379"> </a>In the manager's view, a transaction goes through the following states:
+<p>
+<CENTER>
+<img src="images/txn-spec4.gif" alt="This graphic illustrates the following few paragraphs." height="208" width="480">
+
+</CENTER></p>
+<p class="Body">
+  <a name="10547"> </a>When a transaction is created using <code>create</code>, the transaction is <code>ACTIVE</code>. This is the only state in which participants may <code>join</code> the transaction. Attempting to join the transaction in any other state throws a <code>CannotJoinException</code>.
+</p>
+<p class="Body">
+  <a name="7382"> </a><em class="Emphasis"></em>Invoking the manager's <code>commit</code> method causes the manager to move to the <code>VOTING</code> state, in which it attempts to complete the transaction by rolling forward. Each participant that has joined the transaction has its <code>prepare</code> method invoked to vote on the outcome of the transaction. The participant may return one of three votes: <code>NOTCHANGED</code>, <code>ABORTED</code>, or <code>PREPARED</code>.
+</p>
+<p class="Body">
+  <a name="7383"> </a>If a participant votes <code>ABORTED</code>, the manager must abort the transaction. If <code>prepare</code> throws <code>UnknownTransactionException</code> or <code>NoSuchObjectException</code>, the participant has lost its state of the transaction, and the manager must abort the transaction. If <code>prepare</code> throws <code>RemoteException</code>, the manager may retry as long as it wishes until it decides to abort the transaction.
+</p>
+<p class="Body">
+  <a name="7384"> </a>To abort the transaction, the manager moves to the <code>ABORTED</code> state. In the <code>ABORTED</code> state, the manager should invoke <code>abort</code> on all participants that have voted <code>PREPARED</code>. The manager should also attempt to invoke <code>abort</code> on all participants on which it has not yet invoked <code>prepare</code>. These notifications are not strictly necessary for the one-parameter forms of <code>commit</code> and <code>abort</code>, since the participants will eventually abort the transaction either by timing out or by asking the manager for the state of the transaction. However, informing the participants of the abort can speed up the release of resources in these participants, and so attempting the notification is strongly encouraged.
+</p>
+<p class="Body">
+  <a name="7385"> </a>If a participant votes <code>NOTCHANGED</code>, it is dropped from the list of participants, and no further communication will ensue. If all participants vote <code>NOTCHANGED</code> then the entire transaction was read-only and no participant has any changes to roll forward. The transaction moves to the <code>COMMITTED</code> state and then can immediately move to <em class="Emphasis">cleanup</em>, in which resources in the manager are cleaned up. There is no behavioral difference to a participant between a <code>NOTCHANGED</code> transaction and one that has completed the notification phase of the <code>COMMITTED</code> state.
+</p>
+<p class="Body">
+  <a name="35268"> </a>If no participant votes <code>ABORTED</code> and at least one participant votes <code>PREPARED</code>, the transaction also moves to the <code>COMMITTED</code> state. In the <code>COMMITTED</code> state the manager must notify each participant that returned <code>PREPARED</code> to roll forward by invoking the participant's <code>commit</code> method. When the participant's <code>commit</code> method returns normally, the participant has rolled forward successfully and the manager need not invoke <code>commit</code> on it again. As long as there exists at least one participant that has not rolled forward successfully, the manager must preserve the state of the transaction and repeat attempts to invoke <code>commit</code> at reasonable intervals. If a participant's <code>commit</code> method throws <code>UnknownTransactionException</code>, this means that the participant has already successfully rolled the transaction forward even though the manager did
  not receive the notification, either due to a network failure on a previous invocation that was actually successful or because the participant called <code>getState</code> directly.
+</p>
+<p class="Body">
+  <a name="7387"> </a>If the transaction is a nested one and the manager is prepared to roll the transaction forward, the members of the nested transaction must become members of the parent transaction. This <em class="Emphasis">promotion</em> of participants into the parent manager must be atomic--all must be promoted simultaneously, or none must be. The multi-participant <code>promote</code> method is designed for this use in the case in which the parent and nested transactions have different managers.
+</p>
+<p class="Body">
+  <a name="7388"> </a>The <code>promote</code> method takes arrays of participants and crash counts, where <code>crashCounts[i]</code> is the crash count for <code>parts[i]</code>. If any crash count is different from a crash count that is already known to the parent transaction manager, the parent manager throws <code>CrashCountException</code> and the parent transaction must abort. The <code>drop</code> parameter allows the nested transaction manager to drop itself out of the parent transaction as it promotes its participants into the parent transaction if it no longer has any need to be a participant itself.
+</p>
+<p class="Body">
+  <a name="7389"> </a>The manager for the nested transaction should remain available until it has successfully driven each participant to completion and promoted its participants into the parent transaction. If the nested transaction's manager disappears before a participant is positively informed of the transaction's completion, that participant will not know whether to roll forward or back, forcing it to vote <code>ABORTED</code> in the parent transaction. The manager may cease <code>commit</code> invocations on its participants if any parent transaction is aborted. Aborting any transaction implicitly aborts any uncommitted nested transactions. Additionally, since any committed nested transaction will also have its results dropped, any actions taken on behalf of that transaction can be abandoned.
+</p>
+<p class="Body">
+  <a name="7390"> </a>Invoking the manager's <code>abort</code> method, cancelling the transaction's lease, or allowing the lease to expire also moves the transaction to the <code>ABORTED</code> state. Any transactions nested inside that transaction are also moved directly to the <code>ABORTED</code> state.
+</p>
+<p class="Body">
+  <a name="7391"> </a>If all but one of the participants in a transaction have returned <code>NOTCHANGED</code>, the manager may optimize the <code>VOTING</code> state by invoking that participant's <code>prepareAndCommit</code> method. (Note that this includes the special case in which the transaction has exactly one participant.) If the manager receives an <code>ABORTED</code> result from <code>prepareAndCommit</code>, it proceeds to the <code>ABORTED</code> state. In effect, a <code>prepareAndCommit</code> moves through the <code>VOTING</code> state straight to operating on the results.
+</p>
+<p class="Body">
+As previously noted, a call to <code>prepareAndCommit</code> might not be idempotent. If the manager receives a <code>RemoteException</code> because of network failure, but the participant has successfully moved to the <em>cleanup</em> stage, then the manager will be unable to determine the result of a previous <code>prepareAndCommit</code> call by simply retrying it. At this point, the participant has dropped the information about the transaction and will throw <code>UnknownTransactionException</code> on any retry attempt. When this occurs, the manager must indicate this condition by throwing a <code>RemoteException</code> back to the client. (Note that there is no added benefit of using <code>prepare</code> then <code>commit</code> versus <code>prepareAndCommit</code> in this case.)
+</p>
+
+<p class="Body">
+  <a name="7392"> </a>A <code>getState</code> call on the manager can return any of <code>ACTIVE</code>, <code>VOTING</code>, <code>ABORTED</code>, <code>NOTCHANGED</code>, or <code>COMMITTED</code>. A manager is permitted, but not required, to return <code>NOTCHANGED</code> if it is in the <code>COMMITTED</code> state and all participants voted <code>NOTCHANGED</code>.
+</p>
+<h4 class="Heading3">
+  <a name="7394"> </a>TX.2.8	 Crash Recovery
+</h4>
+<p class="Body">
+  <a name="33489"> </a>Crash recovery ensures that a top-level transaction will consistently abort or roll forward in the face of a system crash. Nested transactions are not involved.
+</p>
+<p class="Body">
+  <a name="33490"> </a>The manager has one <em class="Emphasis">commit point,</em> where it must save state in a durable fashion. This is when it enters the <code>COMMITTED</code> state with at least one <code>PREPARED</code> participant. The manager must, at this point, commit the list of <code>PREPARED</code> participants into durable storage. This storage must persist until all <code>PREPARED</code> participants successfully roll forward. A manager may choose to also store the list of <code>PREPARED</code> participants that have already successfully rolled forward or to rewrite the list of <code>PREPARED</code> participants as it shrinks, but this optimization is not required (although it is recommended as good citizenship). In the event of a manager crash, the list of participants must be recovered, and the manager must continue acting in the <code>COMMITTED</code> state until it can successfully notify all <code>PREPARED</code> participants.
+</p>
+<p class="Body">
+  <a name="7397"> </a>The participant also has one commit point, which is prior to voting <code>PREPARED</code>. When it votes <code>PREPARED</code>, the participant must have durably recorded the record of changes necessary to successfully roll forward in the event of a future invocation of <code>commit</code> by the manager. It can remove this record when it is prepared to successfully return from a <code>commit</code> or an <code>abort</code>.
+</p>
+<p class="Body">
+  <a name="35646"> </a>Because of these commitments, manager and participant implementations should use durable forms of Java RMI references, such as the <code>Activatable</code> references introduced in the Java<font size="-1"><sup>TM</sup></font> 2 platform. An unreachable manager causes much havoc and should be avoided as much as possible. A vanished <code>PREPARED</code> participant puts a transaction in an untenable permanent state in which some, but not all, of the participants have rolled forward.
+</p>
+<h5 class="Heading4">
+  <a name="35649"> </a>TX.2.8.1	 The Roll Decision
+</h5>
+<p class="Body">
+  <a name="35650"> </a>If a participant votes <code>PREPARED</code> for a top-level transaction, it must guarantee that it will execute a recovery process if it crashes between completing its durable record and receiving a <code>commit</code> notification from the manager. This recovery process must read the record of the crashed participant and make a <em class="Emphasis">roll decision</em>--whether to roll the recorded changes forward or roll them back.
+</p>
+<p class="Body">
+  <a name="7402"> </a>To make this decision, it invokes the <code>getState</code> method on the transaction manager. This can have the following results:
+</p>
+<ul>
+  <li class="SmartList1"><a name="35307"> </a><code>getState</code> returns <code>COMMITTED</code>: The recovery should move the participant to the <code>COMMITTED</code> state.<p>
+  <li class="SmartList1"><a name="35308"> </a><code>getState</code> returns <code>ABORTED</code>: The recovery should move the participant to the <code>ABORTED</code> state.<p>
+  <li class="SmartList1"><a name="35308"> </a><code>getState</code> throws either an <code>UnknownTransactionException</code> or a <code>NoSuchObjectException</code>: The recovery should move the participant to the <code>ABORTED</code> state.<p>
+  <li class="SmartList1"><a name="7405"> </a><code>getState</code> throws <code>RemoteException</code>: The recovery should repeat the attempt after a pause.
+</ul>
+<h4 class="Heading3">
+  <a name="7406"> </a>TX.2.9	 Durability
+</h4>
+<p class="Body">
+  <a name="7407"> </a>Durability is a commitment, but it is not a guarantee. It is impossible to guarantee that any given piece of stable storage can <em class="Emphasis">never</em> be lost; one can only achieve decreasing probabilities of loss. Data that is force-written to a disk may be considered durable, but it is less durable than data committed to two or more separate, redundant disks. When we speak of "durability" in this system it is always used relative to the expectations of the human who decided which entities to use for communication.
+</p>
+<p class="Body">
+  <a name="7408"> </a>With multi-participant transactions it is entirely possible that different participants have different durability levels. The manager may be on a tightly replicated system with its durable storage duplicated on several host systems, giving a high degree of durability, while a participant may be using only one disk. Or a participant may always store its data in memory, expecting to lose it in a system crash (a database of people currently logged into the host, for example, need not survive a system crash). When humans make a decision to use a particular manager and set of participants for a transaction they must take into account these differences and be aware of the ramifications of committing changes that may be more durable on one participant than another. Determining, or even defining and exposing, varying levels of durability is outside the scope of this specification.
+</p>
+<h3 class="Heading2">
+  <a name="7472"> </a>TX.3	 Default Transaction Semantics
+</h3>
+<p class="Body">
+  The two-phase commit protocol defines how a transaction is created and later driven to completion by either committing or aborting. It is neutral with respect to the semantics of locking under the transaction or other behaviors that impart semantics to the use of the transaction. Specific clients and servers, however, must be written to expect specific transaction semantics. This model is to separate the completion protocol from transaction semantics, where transaction semantics are represented in the parameters and return values of methods by which clients and participants interact.
+</p>
+<p class="Body">
+  <a name="7475"> </a>This chapter defines the default transaction semantics of services. These semantics preserve the traditional <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties (you will find a brief description of the <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">ACID</span> properties in <a href="txn-spec.html#33449">Section TX.1.2 "Distributed Transactions and ACID Properties"</a>). The semantics are represented by the <code>Transaction</code> and <code>NestableTransaction</code> interfaces and their implementation classes <code>ServerTransaction</code> and <code>NestableServerTransaction</code>. Any participant that accepts as a parameter or returns any of these types is promising to abide by the following definition of semantic
 s for any activities performed under that transaction.
+</p>
+<h4 class="Heading3">
+  <a name="7480"> </a>TX.3.1	 <code>Transaction</code> and <code>NestableTransaction</code> Interfaces
+</h4>
+<p class="Body">
+  <a name="7481"> </a>The client's view of transactions is through two interfaces: <code>Transaction</code> for top-level transactions and <code>NestableTransaction</code> for transactions under which nested transactions can be created. First, the <code>Transaction</code> interface:
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public interface Transaction {
+    public static class Created implements Serializable {
+        public final Transaction transaction;
+        public final Lease lease;
+        Created(Transaction transaction, Lease lease) {...}
+    }
+    void commit()<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotCommitException,
+               RemoteException;
+    void commit(long waitFor)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotCommitException,
+               TimeoutExpiredException, RemoteException;
+    void abort()<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotAbortException,
+               RemoteException; 
+    void abort(long waitFor)<a href="txn-spec.html#7224"> // &#167;TX.2.5</a>
+        throws UnknownTransactionException,
+               CannotAbortException,
+               TimeoutExpiredException, RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="35323"> </a>The <code>Created</code> nested class is used in a factory <code>create</code> method for top-level transactions (defined in the next section) to hold two return values: the newly created <code>Transaction</code> object and the transaction's lease, which is the lease granted by the transaction manager. The <code>commit</code> and <code>abort</code> methods have the same semantics as discussed in <a href="txn-spec.html#7224">Section TX.2.5 "Completing a Transaction: The Client's View"</a>.
+</p>
+<p class="Body">
+  <a name="35327"> </a>Nested transactions are created using <code>NestableTransaction</code> methods:
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public interface NestableTransaction extends Transaction {
+    public static class Created implements Serializable {
+        public final NestableTransaction transaction;
+        public final Lease lease;
+        Created(NestableTransaction transaction, Lease lease)
+            {...}
+    }
+    Created create(long leaseFor)<a href="txn-spec.html#33456"> // &#167;TX.2.2</a>
+        throws UnknownTransactionException,
+               CannotJoinException, LeaseDeniedException,
+               RemoteException;
+    Created create(NestableTransactionManager mgr,
+                   long leaseFor)<a href="txn-spec.html#33456"> // &#167;TX.2.2</a>
+        throws UnknownTransactionException,
+        CannotJoinException, LeaseDeniedException,
+        RemoteException;
+}
+</pre>
+<p class="Body">
+  <a name="10551"> </a>The <code>Created</code> nested class is used to hold two return values: the newly created <code>Transaction</code> object and the transaction's lease, which is the lease granted by the transaction manager. In both <code>create</code> methods, <code>leaseFor</code> is the requested lease time in milliseconds. In the one-parameter <code>create</code> method the nested transaction is created with the same transaction manager as the transaction on which the method is invoked. The other <code>create</code> method can be used to specify a different transaction manager to use for the nested transaction.
+</p>
+<h4 class="Heading3">
+  <a name="7508"> </a>TX.3.2	 <code>TransactionFactory</code> Class
+</h4>
+<p class="Body">
+  <a name="7509"> </a>The <code>TransactionFactory</code> class is used to create top-level transactions.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class TransactionFactory {
+    public static Transaction.Created
+        create(TransactionManager mgr, long leaseFor)
+                                                <a href="txn-spec.html#7139"> // &#167;TX.2.1</a>
+        throws LeaseDeniedException, RemoteException {...}
+    public static NestableTransaction.Created
+        create(NestableTransactionManager mgr,long leaseFor)
+                                                <a href="txn-spec.html#33456"> // &#167;TX.2.2</a>
+        throws LeaseDeniedException, RemoteException {...}
+}
+</pre>
+<p class="Body">
+  <a name="10555"> </a>The first <code>create</code> method is usually used when nested transactions are not required. However, if the manager that is passed to this method is in fact a <code>NestableTransactionManager</code>, then the returned <code>Transaction</code> can in fact be cast to a <code>NestableTransaction</code>. The second <code>create</code> method is used when it is known that nested transactions need to be created. In both cases, a <code>Created</code> instance is used to hold two return values: the newly created transaction object and the granted lease.
+</p>
+<h4 class="Heading3">
+  <a name="7519"> </a>TX.3.3	 <code>ServerTransaction</code> and <code>NestableServerTransaction</code> Classes
+</h4>
+<p class="Body">
+  <a name="7520"> </a>The <code>ServerTransaction</code> class exposes functionality necessary for writing participants that support top-level transactions. Participants can cast a <code>Transaction</code> to a <code>ServerTransaction</code> to obtain access to this functionality.
+<pre  class="Preformatted">public class ServerTransaction
+    implements Transaction, Serializable
+{
+    public final TransactionManager mgr;
+    public final long id;
+    public ServerTransaction(TransactionManager mgr, long id)
+        {...}
+    public void join(TransactionParticipant part,
+                     long crashCount)<a href="txn-spec.html#7194"> // &#167;TX.2.3</a>
+        throws UnknownTransactionException,
+               CannotJoinException, CrashCountException,
+               RemoteException {...}
+    public int getState()<a href="txn-spec.html#7341"> // &#167;TX.2.7</a>
+        throws UnknownTransactionException, RemoteException
+        {...}
+    public boolean isNested() {...}<a href="txn-spec.html#7519"> // &#167;TX.3.3</a>
+}
+</pre>
+<p class="Body">
+  <a name="10557"> </a>The <code>mgr</code> field is a reference to the transaction manager that created the transaction. The <code>id</code> field is the transaction identifier returned by the transaction manager's <code>create</code> method.
+</p>
+<p class="Body">
+  <a name="7533"> </a>The constructor should not be used directly; it is intended for use by the <code>TransactionFactory</code> implementation.
+</p>
+<p class="Body">
+  <a name="7534"> </a>The methods <code>join</code>, <code>commit</code>, <code>abort</code>, and <code>getState</code> invoke the corresponding methods on the manager, passing the transaction identifier. They are provided as a convenience to the programmer, primarily to eliminate the possibility of passing an identifier to the wrong manager. For example, given a <code>ServerTransaction</code> object <code>tr</code>, the invocation
+<pre  class="Preformatted">tr.join(participant, crashCount);
+</pre>
+<p class="Body">
+  <a name="34028"> </a>is equivalent to
+<pre  class="Preformatted">tr.mgr.join(tr.id, participant, crashCount);
+</pre>
+<p class="Body">
+  <a name="7538"> </a>The <code>isNested</code> method returns <code>true</code> if the transaction is a nested transaction (that is, if it is a <code>NestableServerTransaction</code> with a non-<code>null</code> parent) and <code>false</code> otherwise. It is provided as a method on <code>ServerTransaction</code> for the convenience of participants that do not support nested transactions.
+</p>
+<p class="Body">
+  <a name="35345"> </a>The <code>hashCode</code> method returns the <code>id</code> cast to an <code>int</code> <span style="color: #000000; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; vertical-align: baseline">XOR</span>ed with the result of <code>mgr.hashCode()</code>. The <code>equals</code> method returns <code>true</code> if the specified object is a <code>ServerTransaction</code> object with the same manager and transaction identifier as the object on which it is invoked.
+</p>
+<p class="Body">
+  <a name="35346"> </a>The <code>NestableServerTransaction</code> class exposes functionality that is necessary for writing participants that support nested transactions. Participants can cast a <code>NestableTransaction</code> to a <code>NestableServerTransaction</code> to obtain access to this functionality.
+<pre  class="Preformatted">package net.jini.core.transaction.server;
+
+public class NestableServerTransaction
+    extendsServerTransaction implements NestableTransaction
+{
+    public final NestableServerTransaction parent;
+    public NestableServerTransaction(
+           NestableTransactionManager mgr, long id,
+           NestableServerTransaction parent) {...}
+    public void promote(TransactionParticipant[] parts,
+                        long[] crashCounts,
+                        TransactionParticipant drop)
+                                                   <a href="txn-spec.html#7341"> // &#167;TX.2.7</a>
+        throws UnknownTransactionException,
+    &nbsp;          CannotJoinException, CrashCountException,
+               RemoteException {...}
+    public boolean enclosedBy(NestableTransaction enclosing)
+        {...}
+}
+</pre>
+<p class="Body">
+  <a name="10561"> </a>The <code>parent</code> field is a reference to the parent transaction if the transaction is nested (see <a href="txn-spec.html#33456">Section TX.2.2 "Starting a Nested Transaction"</a>) or <code>null</code> if it is a top-level transaction.
+</p>
+<p class="Body">
+  <a name="7549"> </a>The constructor should not be used directly; it is intended for use by the <code>TransactionFactory</code> and <code>NestableServerTransaction</code> implementations.
+</p>
+<p class="Body">
+  <a name="7550"> </a>Given a <code>NestableServerTransaction</code> object <code>tr</code>, the invocation
+<pre  class="Preformatted">tr.promote(parts, crashCounts, drop)
+</pre>
+<p class="Body">
+  <a name="7552"> </a>is equivalent to
+<pre  class="Preformatted">((NestableTransactionManager)tr.mgr).promote(tr.id, parts,
+                                            crashCounts, drop)
+</pre>
+<p class="Body">
+  <a name="34080"> </a>The <code>enclosedBy</code> method returns <code>true</code> if the specified transaction is an enclosing transaction (parent, grandparent, etc.) of the transaction on which the method is invoked; otherwise it returns <code>false</code>.
+</p>
+<h4 class="Heading3">
+  <a name="7555"> </a>TX.3.4	 <code>CannotNestException</code> Class
+</h4>
+<p class="Body">
+  <a name="7556"> </a>If a service implements the default transaction semantics but does not support nested transactions, it usually needs to throw an exception if a nested transaction is passed to it. The <code>CannotNestException</code> is provided as a convenience for this purpose, although a service is not required to use this specific exception.
+<pre  class="Preformatted">package net.jini.core.transaction;
+
+public class CannotNestException extends TransactionException
+{
+    public CannotNestException() {...}
+    public CannotNestException(String desc) {...}
+}
+</pre>
+<h4 class="Heading3">
+  <a name="34097"> </a>TX.3.5	 Semantics
+</h4>
+<p class="Body">
+  <a name="7559"> </a>Activities that are performed as pure transactions (all access to shared mutable state is performed under transactional control) are subject to sequential ordering, meaning the overall effect of executing a set of sibling (all at the same level, whether top-level or nested) pure transactions concurrently is always equivalent to some sequential execution.
+</p>
+<p class="Body">
+  <a name="7560"> </a>Ancestor transactions can execute concurrently with child transactions, subject to the locking rules below.
+</p>
+<p class="Body">
+  <a name="7561"> </a>Transaction semantics for objects are defined in terms of strict two-phase locking. Every transactional operation is described in terms of acquiring locks on objects; these locks are held until the transaction completes. The most typical locks are read and write locks, but others are possible. Whatever the lock types are, conflict rules are defined such that if two operations do not commute, then they acquire conflicting locks. For objects using standard read and write locks, read locks do not conflict with other read locks, but write locks conflict with both read locks and other write locks. A transaction can acquire a lock if the only conflicting locks are those held by ancestor transactions (or itself). If a necessary lock cannot be acquired and the operation is defined to proceed without waiting for that lock, then serializability might be violated. When a subtransaction commits, its locks are inherited by the parent transaction.
+</p>
+<p class="Body">
+  <a name="35351"> </a>In addition to locks, transactional operations can be defined in terms of object creation and deletion visibility. If an object is defined to be created under a transaction, then the existence of the object is visible only within that transaction and its inferiors, but will disappear if the transaction aborts. If an object is defined to be deleted under a transaction, then the object is not visible to any transaction (including the deleting transaction) but will reappear if the transaction aborts. When a nested transaction commits, visibility state is inherited by the parent transaction.
+</p>
+<p class="Body">
+  <a name="7563"> </a>Once a transaction reaches the <code>VOTING</code> stage, if all execution under the transaction (and its subtransactions) has finished, then the only reasons the transaction can abort are:
+</p>
+<ul>
+  <li class="SmartList1"><a name="7564"> </a>The manager crashes (or has crashed) <p>
+  <li class="SmartList1"><a name="7565"> </a>One or more participants crash (or have crashed)<p>
+  <li class="SmartList1"><a name="7566"> </a>There is an explicit abort
+</ul>
+<p class="Body">
+  <a name="7567"> </a>Transaction deadlocks are not guaranteed to be prevented or even detected, but managers and participants are permitted to break known deadlocks by aborting transactions.
+</p>
+<p class="Body">
+  <a name="35360"> </a>An active transaction is an <em class="Emphasis">orphan</em> if it or one of its ancestors is guaranteed to abort. This can occur because an ancestor has explicitly aborted or because some participant or manager of the transaction or an ancestor has crashed. Orphans are not guaranteed to be detected by the system, so programmers using transactions must be aware that orphans can see internally inconsistent state and take appropriate action.
+</p>
+<p class="Body">
+  <a name="35367"> </a>Causal ordering information about transactions is not guaranteed to be propagated. First, given two sibling transactions (at any level), it is not possible to tell whether they were created concurrently or sequentially (or in what order). Second, if two transactions are causally ordered and the earlier transaction has completed, the outcome of the earlier transaction is not guaranteed to be known at every participant used by the later transaction, unless the client is successful in using the variant of <code>commit</code> or <code>abort</code> that takes a timeout parameter. Programmers using non-blocking forms of operations must take this into account.Furthermore, the default semantics do not require the participants to implement atomic versions of <code>commit</code> and <code>abort</code>.
+</p>
+<p class="Body">
+  <a name="7570"> </a>As long as a transaction persists in attempting to acquire a lock that conflicts with another transaction, the participant will persist in attempting to resolve the outcome of the transaction that holds the conflicting lock. Attempts to acquire a lock include making a blocking call, continuing to make non-blocking calls, and registering for event notification under a transaction.
+</p>
+<h4 class="Heading3">
+  <a name="7571"> </a>TX.3.6	 Serialized Forms
+<P><CENTER>
+<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
+       cellpadding="5" cellspacing="0" Summary="serialized forms of the classes listed below">
+  <caption></caption>
+  <tr bgcolor="#CCCCCC">
+    <th>Class<br></th>
+    <th><code>serialVersionUID</code><br></th>
+    <th>Serialized Fields<br></th>
+  </tr>
+  <tr>
+    <td><code>Transaction.Created</code><br></td>
+    <td>-5199291723008952986L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>NestableTransaction.Created</code><br></td>
+    <td>-2979247545926318953L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>TransactionManager.Created</code><br></td>
+    <td>-4233846033773471113L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>ServerTransaction</code><br></td>
+    <td>4552277137549765374L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>NestableServerTransaction</code><br></td>
+    <td>-3438419132543972925L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>TransactionException</code><br></td>
+    <td>-5009935764793203986L<br></td>
+    <td><em class="Emphasis">none</em></td>
+</tr>
+  <tr>
+    <td><code>CannotAbortException</code><br></td>
+    <td>3597101646737510009L<br></td>
+    <td><em class="Emphasis">none</em></td>
+  </tr>
+  <tr>
+    <td><code>CannotCommitException</code><br></td>
+    <td>-4497341152359563957L<br></td>
+    <td><em class="Emphasis">none</em></td>
+  </tr>
+  <tr>
+    <td><code>CannotJoinException</code><br></td>
+    <td>5568393043937204939L<br></td>
+    <td><em class="Emphasis">none</em></td>
+  </tr>
+  <tr>
+    <td><code>CannotNestException</code><br></td>
+    <td>3409604500491735434L<br></td>
+    <td><em class="Emphasis">none</em></td>
+  </tr>
+  <tr>
+    <td><code>TimeoutExpiredException</code><br></td>
+    <td>3918773760682958000L<br></td>
+    <td><em class="Emphasis">all public fields</em></td>
+  </tr>
+  <tr>
+    <td><code>UnknownTransactionException</code><br></td>
+    <td>443798629936327009L<br></td>
+    <td><em class="Emphasis">none</em></td>
+  </tr>
+  <tr>
+    <td><a name="34738"> </a><code>CrashCountException</code><br></td>
+    <td><a name="34768"> </a>4299226125245015671L<br></td>
+    <td><a name="34742"> </a><em class="Emphasis">none</em></td>
+  </tr>
+</table>
+</CENTER>
+
+
+
+<h3 class="Heading2">
+  <a name="43987"> </a>TX.4	 History</h3>
+<p>
+<table align="center" border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000" cellpadding="5" cellspacing="0" summary="history of this specification">
+  <caption><p class="Body">
+  <a name="01887"> </a>
+</p>
+</caption>
+  <tr bgcolor="#CCCCCC">
+    <th>Version</th>
+    <th>Description</th>
+  </tr>
+ <tr>
+    <td valign="top">v1.0
+	</td>
+    <td>Initial release of this specification.
+</td>
+  </tr>
+  <tr>
+    <td valign="top">v2.0
+	</td>
+    <td>Added History section (TX.4)<br>
+       Clarified that transactions rely on Java RMI semantics (TX.1.3)<br>
+       Removed crash count example (TX.2.3)<br>
+       Clarified language with respect to abort and participants and corrected permissible return values for the <code>prepare</code> method. (TX.2.7)<br>
+       Clarified commit point removal and <code>getState</code> semantics (TX.2.8)<br>
+       Clarified idempotentcy of <code>prepareAndCommit</code> (TX.2.6, TX.2.7)<br>
+       Clarified atomicity of participant <code>abort</code> and <code>commit</code> (TX.3.5)<br>
+       Changed semantics of <code>prepareAndCommit</code> logic (TX.2.6)
+</td>
+  </tr>
+</table>
+
+<h3 class="Heading2">
+  <a name="0188"> </a>		 License	 
+</h3>
+<p>
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+<ul>
+     <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
+</ul>
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+</blockquote>
+
+<hr>
+<a href="#skip" title="Skip navigation bar"></a>
+<table width="100%"><tr>
+<td align=left><a href="../../spec-index.html">Spec Index</a>
+<td align=right><em>Jini Technology Core Platform Specifications</em></td>
+</tr></table>
+<a name="skip"></a>
+
+<hr>
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+<ul>
+     <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
+</ul>
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+</body>
+</html>
+
+<!-- This HTML file was initially created with Quadralay WebWorks Publisher 3.5.0 -->
+<!-- by Susan Snyder -->
+<!-- Last updated: 01/27/05 -->
+



Mime
View raw message