KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > FixtureOverlays


1 /**
2  * $Id: FixtureOverlays.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2002-2005 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your option) any later
9  * version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx;
30
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.Project;
33
34 import com.idaremedia.antx.apis.ProblemHandler;
35
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Stack JavaDoc;
40
41 /**
42  * Administrator of thread-local stacks of iteration settings. As the run context
43  * moves through different targets and tasks certain settings need to move between
44  * these entities independent of the current Ant project instance. Since Ant tasks
45  * like &lt;antcall&gt; create new child project instances it is difficult for
46  * a configuration task to declare a setting at build-iteration level (attaching
47  * properties to the project may or may not propagate the settings properly depending
48  * on how the &lt;antcall&gt; is declared). FixtureOverlays transcends projects, targets,
49  * and tasks and is the foundation for many AntX configuration tasks.
50  * <p/>
51  * FixtureOverlays tries to be very tolerant to support blind-resets when tasks are
52  * unwinding from an exception condition. FixtureOverlays should <em>not</em> be used
53  * to store permanent, iteration independent, information because overlays will be
54  * torn down for each new iteration regardless of whether the enclosing Ant runtime
55  * remains intact (for example if builds are being launched from an always on
56  * "Ant console").
57  * <p/>
58  * Classes that use fixture overlays usually provide a public administration facade
59  * utility (like {@linkplain UISMContext}) and an associated kill method for execution
60  * harnesses.
61  *
62  * @since JWare/AntX 0.1 (originally Iteration)
63  * @author ssmc, &copy;2002-2005 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
64  * @version 0.5
65  * @.safety guarded
66  * @.group impl,infra
67  * @see KillMethod
68  **/

69
70 public final class FixtureOverlays implements FixtureCore, FixtureAdministrator, Cloneable JavaDoc
71 {
72     /**
73      * Initializes a new empty overlays object.
74      **/

75     FixtureOverlays()
76     { }
77
78
79
80     /**
81      * Returns a <em>deep</em> clone of this overlays instance. The returned
82      * copy is completely independent of this instance, so changing its
83      * callstack has no effect on this one.
84      **/

85     public synchronized Object JavaDoc clone()
86     {
87         try {
88             FixtureOverlays copy = (FixtureOverlays)super.clone();
89             copy.m_Env = (HashMap JavaDoc)m_Env.clone();
90             Iterator JavaDoc itr = m_Env.entrySet().iterator();
91             while (itr.hasNext()) {
92                 Map.Entry JavaDoc mE= (Map.Entry JavaDoc)itr.next();
93                 copy.m_Env.put(mE.getKey(),((Stack JavaDoc)mE.getValue()).clone());
94             }
95             copy.m_invalidCalls=0;
96             return copy;
97         } catch(CloneNotSupportedException JavaDoc clnx) {
98             throw new InternalError JavaDoc(AntX.uistrs().get(AntX.CLONE_BROKEN_MSGID));
99         }
100     }
101
102
103
104     /**
105      * Returns the current ("frontmost") setting associated with given
106      * category. Returns <i>null</i> if category has no current setting.
107      * @param category settings category (like 'UISM' or 'Logs', etc.)
108      **/

109     public synchronized Object JavaDoc nearest(Object JavaDoc category)
110     {
111         Stack JavaDoc all = callstack(category);
112         if (all==null || all.isEmpty()) {
113             return null;
114         }
115         return all.peek();
116     }
117
118
119
120     /**
121      * Installs a new ("frontmost") setting for the given overlay
122      * category. The new setting cannot be <i>null</i>. The method
123      * returns the previous setting, providing a single locked get/set
124      * operation.
125      * @param category variable category (like 'UISM' or 'Emitter', etc.)
126      * @param current the most-recent setting in category (non-null)
127      * @return previous category setting (can be null)
128      * @see FixtureIds
129      **/

130     public synchronized Object JavaDoc install(Object JavaDoc category, Object JavaDoc current)
131     {
132         Object JavaDoc previous = null;
133         Stack JavaDoc all = callstack(category);
134
135         if (all==null) {
136             all = create(category);
137         } else if (!all.isEmpty()) {
138             previous = all.peek();
139         }
140
141         all.push(current);
142         return previous;
143     }
144
145
146
147     /**
148      * Zaps the most recent setting for a category from this overlays.
149      * No-op if category has no active settings.
150      * @param category settings category (like 'UISM' or 'Logs', etc.)
151      * @return <i>true</i> if unwound occured, else <i>false</i>
152      **/

153     public synchronized boolean unwind(Object JavaDoc category)
154     {
155         boolean popped = true;
156         Stack JavaDoc all = callstack(category);
157
158         if (all!=null && !all.isEmpty()) {
159             all.pop();
160         } else {
161             m_invalidCalls++;
162             popped = false;
163         }
164         return popped;
165     }
166
167
168
169     /**
170      * Clears all settings for a particular category from this overlays.
171      * Your application should never use this method directly; it
172      * is provided for overlays clients to provide a kill method to the
173      * execution or test harness.
174      * @param category settings category (non-null)
175      * @return <i>true</i> if category cleared
176      * @since JWare/AntX 0.4
177      **/

178     public synchronized boolean clear(Object JavaDoc category)
179     {
180         Stack JavaDoc all = callstack(category);
181         if (all!=null) {
182             all.clear();
183             return true;
184         }
185         return false;
186     }
187
188
189
190     /**
191      * Returns <i>true</i> if an object is already installed on a
192      * category's stack. Useful for categorys that require a single instance
193      * of any particular object on the stack at any one time. The check
194      * verifies object equality by using the incoming object's 'equals' method.
195      **/

196     public synchronized boolean isInstalled(Object JavaDoc category, Object JavaDoc current)
197     {
198         if (current==null) {
199             throw new IllegalArgumentException JavaDoc("isInstalled- NULL object");
200         }
201         Stack JavaDoc all = callstack(category);
202         if (all!=null) {
203             return all.contains(current);
204         }
205         return false;
206     }
207
208
209
210     /**
211      * Installs an object into a category iff it doesn't already exist
212      * on category's current thread stack. Common template method for many
213      * iteration-based fixture administrators. Usually called by category
214      * adminstrator's public-facing install method.
215      * @param category variable category
216      * @param next next visible category setting (non-null)
217      * @param noInstallHandler [optional] callback if unable to install
218      * @param what who's calling (used in any error messages)
219      * @since JWare/AntX 0.3
220      * @throws BuildException if unable to install category object
221      **/

222     public static Object JavaDoc installIfNot(Object JavaDoc category, Object JavaDoc next,
223                                       ProblemHandler noInstallHandler,
224                                       String JavaDoc what)
225     {
226         FixtureOverlays overlays = FixtureOverlays.getContextInstance();
227         synchronized(overlays) {
228             if (overlays.isInstalled(category,next)) {
229                 String JavaDoc error = AntX.uistrs().get("context.install.once",what);
230                 if (noInstallHandler!=null) {
231                     noInstallHandler.problem(error,Project.MSG_ERR);
232                 }
233                 throw new BuildException(error);
234             }
235             return overlays.install(category,next);
236         }
237     }
238
239
240
241     /**
242      * Removes the most recently installed object for a particular category.
243      * The previous installation is reactivated, or if this was only object,
244      * the current thread's category object becomes undefined. Common template
245      * method for many iteration-based administrators. Usually called by
246      * category administrator's public-facing uninstall method.
247      * @param category variable category
248      * @param noUninstallHandler [optional] callback if unable to uninstall
249      * @param what who's calling (used in any error messages)
250      * @since JWare/AntX 0.3
251      **/

252     public static void uninstallIfIs(Object JavaDoc category,
253                                      ProblemHandler noUninstallHandler,
254                                      String JavaDoc what)
255     {
256         FixtureOverlays overlays = FixtureOverlays.getContextInstance();
257         if (!overlays.unwind(category) && noUninstallHandler!=null) {
258             String JavaDoc warning = AntX.uistrs().get("context.all.uninstalled",what);
259             noUninstallHandler.problem(warning,Project.MSG_WARN);
260         }
261     }
262
263
264
265     /**
266      * Hook for error-reporting. Necessary to determine if inappropriate
267      * unwinds have been done.
268      **/

269     public synchronized int numberInvalidUnwinds()
270     {
271         return m_invalidCalls;
272     }
273
274
275
276     /**
277      * Returns the stack used to a particular category. Returns <i>null</i>
278      * if not such stack.
279      **/

280     private Stack JavaDoc callstack(Object JavaDoc category)
281     {
282         if (category==null) {
283             throw new IllegalArgumentException JavaDoc("callstack- NULL category");
284         }
285         return (Stack JavaDoc)m_Env.get(category);
286     }
287
288
289
290     /**
291      * Factory method to create a category's settings stack. Automatically
292      * installs the stack into this iteration context's map.
293      **/

294     private Stack JavaDoc create(Object JavaDoc category)
295     {
296         Stack JavaDoc all = new Stack JavaDoc();
297         m_Env.put(category, all);
298         return all;
299     }
300
301
302     private HashMap JavaDoc m_Env = new HashMap JavaDoc(31,0.85f);
303     private int m_invalidCalls;
304
305
306     //------------------------------------------------------------------------------------------|
307

308     /**
309      * Thread-based handle to a single FixtureOverlays instance. Child threads are given their
310      * own independent copies of the handled iteration instance. Changes to the child's
311      * context will not affect its parent.
312      *
313      * @since JWare/AntX 0.1
314      * @author ssmc, &copy;2002-2003 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
315      * @version 0.5
316      * @.safety guarded
317      *
318      **/

319     public static final class Handle extends InheritableThreadLocal JavaDoc
320     {
321         /**
322          * Creates new thread-local handle to an iteration.
323          **/

324         public Handle()
325         {
326             super();
327         }
328
329         /**
330          * A spanking new FixtureOverlays instance.
331          **/

332         protected Object JavaDoc initialValue()
333         {
334             return new FixtureOverlays();
335         }
336
337         /**
338          * A spanking new FixtureOverlays clone of parent's value.
339          **/

340         protected Object JavaDoc childValue(Object JavaDoc parentValue)
341         {
342             return ((FixtureOverlays)parentValue).clone();
343         }
344     }
345
346
347     //------------------------------------------------------------------------------------------|
348

349
350     /**
351      * Returns the current thread's iteration settings. This thread-specific
352      * variable is shared by all objects within the same thread. Usually, a class's
353      * implementation provides an administrator to manage its context-specific
354      * information.
355      * @see FixtureIds
356      * @see FixtureAdministrator
357      **/

358     public static final FixtureOverlays getContextInstance()
359     {
360         return (FixtureOverlays)Iteration.fixtureOverlays().get();
361     }
362 }
363
364 /* end-of-FixtureOverlays.java */
365
Popular Tags