Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javax/ide/model/java/source/write/TreeManager.java


1   /*
2    * @(#)TreeManager.java
3    */
4   
5   package javax.ide.model.java.source.write;
6   
7   import java.net.URI;
8   import javax.ide.model.java.source.tree.FileT;
9   
10  /**
11   * The TreeManager serves as a FileT factory. Clients obtain FileTs by
12   * requesting a FileT from the manager and by creating empty FileTs
13   * through the manager. Clients change the writability of FileTs by
14   * opening and closing TreeTransactions. For the sake of transaction
15   * consistency, a FileT belongs to exactly one TreeManager for the
16   * lifetime of the FileT. <p/>
17   * 
18   * The TreeManager owns a single lockable resource (which may be itself)
19   * which must, at the minumum, provide the functionality of a read-write
20   * lock. Each FileT is tied to a single lockable resource (which may be
21   * itself) which is defined by the owning IDE and which must NOT coincide
22   * with the TreeManager's lock. This is usually an IDE lock controlling
23   * the writable of the underlying resource, e.g. {@link java.io.File}.
24   * Because the FileT's lock is not defined by the owning IDE and not the
25   * owning TreeManager, it is the responsibility (or neglect) of the owning
26   * IDE to safeguard against deadlocks and starvation. <p/>
27   * 
28   * Attempting to make any change to a FileT marked as read-only will
29   * result in an IllegalStateException. Attempting to mark a FileT as
30   * writable when the FileT's underlying resource is not writable may
31   * result in a RuntimeException, at the discretion of the owning IDE.
32   * Although a FileT is logically writable only on the thread that made
33   * it writable, this manager does not enforce that policy. <p/>
34   * 
35   * To start a multi-tree transaction, call
36   * <code>beginMultiTransaction</code> on this manager. To start a
37   * single-tree transaction, call <code>beginTransaction</code> on the
38   * FileT in question. <p/>
39   *
40   * Opening a new transaction that conflicts with an already open
41   * transaction results in a TreeTransactionException. This TreeManager
42   * does not provide blocking operations on its transaction state.
43   * Attempting to close a transaction on a thread different than than
44   * the opening thread results in a TreeTransactionException. A nested
45   * transaction is not considered to be at conflict with its enclosing
46   * transaction. Please see the section on nested transactions further
47   * below for more detail. <p/>
48   *
49   * TODO: If we were to provide such blocking operations, what would they
50   * look like? <p/>
51   * 
52   * 
53   * <h3> Write on commit </h3>
54   *
55   * The change to the underlying source file is not made until the
56   * owning transaction is committed. Transactions collect changes made
57   * to a FileT and then write them out to disk on commit. The only
58   * exception to this is anonymous FileTs, which have no underlying
59   * file. This is done to ensure that IDE listeners fire at the right
60   * time. Thus, a FileT change is not considered to be "done" by the
61   * IDE until its owning transaction has been committed. <p/>
62   *
63   *
64   * <h3> Transaction states </h3>
65   * 
66   * A TreeManager can be in one of three states: read-only, single-tree
67   * transactions open, multi-tree transaction open. These states map
68   * directly to the state of a single read-write lock: read-only,
69   * locked shared, locked exclusive. The scope of a single-tree transaction
70   * is a single FileT. The scope of a multi-tree transaction is a
71   * TreeManager and all its owned FileTs. <p/>
72   * 
73   * In a read-only state, no changes are allowed. All owned FileTs are
74   * marked as read-only. Opening a single-tree transaction on a FileT
75   * belonging to this manager moves this manager into a single-tree
76   * transactions open state. Opening a multi-tree transaction on this
77   * manager moves this manager into a multi-tree transaction open state.
78   * <p/>
79   * 
80   * In a single-tree transactions open state, multiple single-tree
81   * transactions may be open with at most one transaction open per FileT.
82   * In this state, an owned FileT is writable if and only if there is an
83   * open single-tree transaction on said FileT. When all open transactions
84   * are closed on FileTs belonging to this manager, this manager moves into
85   * a read-only state. <p/>
86   * 
87   * In a multi-tree transaction open state, there is a single open
88   * multi-tree transaction. Any change to a FileT belonging to this manager
89   * automatically marks it as writable. When the open transaction is closed,
90   * this manager moves into a read-only state. <p/>
91   * 
92   * TODO: Should we provide the ability to upgrade from a single-tree
93   * transactions open state to a multi-tree transaction open state? Clearly,
94   * such an ability requires the ability of the manager's underlying lock
95   * to upgrade from a locked shared to a locked exclusive state. <p/>
96   * 
97   * 
98   * <h3> Nested transactions </h3>
99   * 
100  * A single-tree transaction is nested if and only if, on open, there
101  * was already an open single-tree transaction on the target FileT or
102  * there was already an open multi-tree transaction on the owning
103  * manager. A multi-tree transaction is nested if and only if, on open,
104  * there was already on open multi-tree transaction on the target
105  * manager. <p/>
106  * 
107  * At this writing, nested transactions are not supported and result
108  * in a TreeTransactionException. They may be supported in a later
109  * release. <p/>
110  * 
111  * 
112  * @author Andy Yu
113  */
114 public interface TreeManager
115 {
116   // ----------------------------------------------------------------------
117   
118   /**
119    * Fetches the FileT for the given Java source URI (*.java).  The
120    * classes contained in teh file represented by the URI can be
121    * fetched from the source file. If the URI does not represent a
122    * valid Java source file, or if the URI points to a non-existing
123    * file, then null is returned. <p/>
124    *
125    * Newly fetched FileTs are marked read-only. Previously fetched
126    * FileTs retain their previous read-only/writable state.<p/>
127    *
128    * @param sourceURI The target URI.
129    *
130    * @return The FileT representing the compilation unit at the
131    *          specified URI.
132    */
133   public FileT getSourceFile(URI sourceURI);
134 
135   /**
136    * Creates a new FileT for the given Java source URI (*.java). This
137    * will create a new empty file for the given URI, and return the
138    * FileT instance for it. If the file already exists on disk, then
139    * this will return null. <p/>
140    *
141    * FileTs may only be created when the TreeManager is in a
142    * multi-tree transaction open state. Hence, the FileT becomes
143    * writable once touched. <p/>
144    *
145    * @param sourceURI The target URI.
146    *
147    * @return The FileT for the newly created compilation unit at the
148    *         specified URI, null if the file was not created.
149    *
150    * @throws IOException if the new file cannot be created.
151    *
152    * @throws IllegalArgumentException if the URI is not recognized as
153    *                                  a Java source file.
154    *
155    * @throws TreeTransactionException if this manager is not in
156    *                                  the multi-tree transaction open state.
157    */
158   public FileT createSourceFile(URI sourceURI);
159 
160   /**
161    * Fetches an anonymous file. <p/>
162    *
163    * An anonymous file is not attached to any URI or lockable
164    * resource, can not be referenced outside, is always writable, and
165    * does not participate in transaction mechanics. In particular, an
166    * anonymous file can not have open transactions, is not affected by
167    * the owning manager's transaction state, and does not affect the
168    * owning manager's transaction state. All TreeResolver operations
169    * may be validly performed on the anonymous file as on any other
170    * file.  <p/>
171    *
172    * This is useful for debugging features who may need to parse
173    * anonymous expressions. <p/>
174    *
175    * Must always return a different non-null FileT each time. <p/>
176    *
177    * @return A FileT for an anonymous file.
178    */
179   public FileT getAnonymousFile();
180   
181   /**
182    * Clears the destination FileT (unlinks all its children), clones
183    * the source FileT contents, and links the cloned Trees into the
184    * destination FileT. No transactions are opened in the process.
185    * The source FileT may be an anoymous file and may even belong to a
186    * different TreeManager. <p/>
187    *
188    * If the destination FileT cannot be written to, an exception will
189    * be thrown. <p/>
190    *
191    * @param source The source FileT.
192    * @param destination The destination FileT.
193    */
194   public void cloneSourceFile(FileT source, FileT destination);
195 
196   /**
197    * Places this FileFactory in an exclusive open transaction state.
198    * Begins a multi-tree transaction. End the transaction with either
199    * {@link MultiTreeTransaction#abort()} or
200    * {@link MultiTreeTransaction#commit()}. <p/>
201    * 
202    * @return The transaction object for the newly begun multi-tree
203    * transaction.
204    */
205   public MultiTreeTransaction beginMultiTransaction();
206   
207   /**
208    * Returns the in-progress multi-tree transaction, null if none.
209    * 
210    * @return The in-progress transaction object, null if none.
211    */
212   public MultiTreeTransaction getMultiTransaction();
213 }