KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > ownhelpers > ProjectPropertiesNet


1 /**
2  * $Id: ProjectPropertiesNet.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2004 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 (LGPL) as published
8  * by the Free Software Foundation; either version 2.1 of the License, or (at your option)
9  * any later 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 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 GNU 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.ownhelpers;
30
31 import java.util.Collections JavaDoc;
32 import java.util.Hashtable JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Map JavaDoc;
35
36 import org.apache.tools.ant.BuildException;
37 import org.apache.tools.ant.Project;
38 import org.apache.tools.ant.PropertyHelper;
39
40 import com.idaremedia.antx.AntX;
41 import com.idaremedia.antx.AntXFixture;
42 import com.idaremedia.antx.FixtureExaminer;
43 import com.idaremedia.antx.apis.Nameable;
44 import com.idaremedia.antx.apis.ProblemHandler;
45 import com.idaremedia.antx.apis.ProjectDependent;
46
47 /**
48  * A <span class="src">ProjectPropertiesNet</span> is usually installed for a
49  * well-defined "execution bubble" to block scoped changes from affecting the
50  * caller's environment. This class is not written as a complete substitute for
51  * the standard Ant PropertyHelper (partially because that class is officially
52  * still in flux as is likely to change dramatically in the future).
53  * <p>
54  * A ProjectPropertiesNet's name and project should be set once by the controlling
55  * task as these methods are not guarded against concurrent use/modification.
56  *
57  * @since JWare/AntX 0.4
58  * @author ssmc, &copy;2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
59  * @version 0.5
60  * @.safety guarded (client APIs only)
61  * @.group impl,helper
62  * @.pattern GoF.Proxy
63  * @.expects Ant 1.6+
64  * @.caveat The PropertyHelper must be manually installed by the controlling
65  * task.
66  * @.caveat As of 1.6.1 custom PropertyHelpers are <em>not</em> propagated to
67  * child projects.
68  * @.caveat Properties provided by a local hook configuration task are not
69  * included in returned property sets (like {@linkplain #getProperties}).
70  * @.impl This net must be workable with our own {@linkplain ScopedProperties}!
71  * @.impl Direct access to project references map is intentional to avoid
72  * the spurious warnings about replaced references.
73  **/

74
75 public final class ProjectPropertiesNet extends PropertyHelper
76     implements ProjectDependent, Nameable
77 {
78     private static final String JavaDoc IAM_ = AntX.utilities+"PropertiesNet";
79
80
81     /**
82      * Reference under which a custom project PropertyHelper
83      * will be installed.
84      */

85     public static final String JavaDoc ANT_HELPER_REFID= "ant.PropertyHelper";
86
87
88
89     /**
90      * Initializes a new properties net. This net's project
91      * must be defined before it is installed.
92      **/

93     public ProjectPropertiesNet()
94     {
95         super();
96     }
97
98
99
100     /**
101      * Initializes and installs a new properties net.
102      * @param name [optional] this net's script-facing label
103      * @param project associated project (non-null)
104      * @throws IllegalStateException if this net is not associated
105      * with a project.
106      **/

107     public ProjectPropertiesNet(String JavaDoc name, Project project)
108     {
109         super();
110         setProject(project);
111         if (name!=null) {
112             setName(name);
113         }
114         install(project);
115     }
116
117
118
119     /**
120      * Set this net's initial set of overlayed properties en-masse.
121      * This method should be called <em>before</em> this net is installed.
122      * Net assumes ownership of incoming properties map. Like any property,
123      * empty seeded values are writable once.
124      * @param properties initial collection of property values (non-null)
125      * @param control <i>true</i> if these are control properties (readonly implied)
126      * @param readonly <i>true</i> if these should be immutable properties
127      * @since JWare/AntX 0.5
128      * @.safety single
129      **/

130     public void seedProperties(Map JavaDoc properties, boolean control, boolean readonly)
131     {
132         AntX.require_(properties!=null,IAM_,"seed- nonzro property set");
133         if (!properties.isEmpty()) {
134             if (control) {
135                 m_controlProperties.putAll(properties);
136                 m_cliProperties.putAll(properties);
137             } else if (readonly) {
138                 m_cliProperties.putAll(properties);
139             } else {
140                 Iterator JavaDoc itr= properties.entrySet().iterator();
141                 while (itr.hasNext()) {
142                     Map.Entry JavaDoc e = (Map.Entry JavaDoc)itr.next();
143                     String JavaDoc value = (String JavaDoc)e.getValue();
144                     if (value==null || value.length()==0) {
145                         e.setValue(EMPTY);
146                     }
147                 }
148                 m_rwProperties = properties;
149             }
150             m_allProperties.putAll(properties);
151         }
152     }
153
154
155
156     /**
157      * Associates this net with a project. This net still has
158      * to be {@linkplain #install(Project) installed} explicitly.
159      * @.safety single
160      **/

161     public void setProject(Project project)
162     {
163         super.setProject(project);
164         m_project = project;
165     }
166
167
168
169     /**
170      * Returns the project with which this net associated.
171      * Can return <i>null</i> if not linked to any project.
172      * @.safety single
173      **/

174     public Project getProject()
175     {
176         return m_project;
177     }
178
179
180
181     /**
182      * Initializes this net's diagnostics-friendly name.
183      * @param name net's name (non-null)
184      * @.safety single
185      **/

186     public final void setName(String JavaDoc name)
187     {
188         AntX.require_(name!=null,IAM_,"setName- nonzro name");
189         m_nameImpl = name;
190     }
191
192
193
194     /**
195      * Returns this net's diagnostics label. Will return
196      * "undefined" if never set explicitly.
197      * @.safety single
198      */

199     public final String JavaDoc getName()
200     {
201         return m_nameImpl;
202     }
203
204
205
206     /**
207      * Ensure this net is not already installed in the given project's
208      * property helper (or hook chain). Prevents infinite (circular) lookups.
209      **/

210     private void verifyNotInChain_(PropertyHelper ph, Project P)
211     {
212         AntX.verify_(ph!=null,IAM_,"install- Ant env inited");
213         do {
214            if (ph==this) {
215                 String JavaDoc error = AntX.uistrs().get("fixture.ph.install.once",getName());
216                 P.log(error,Project.MSG_ERR);
217                 throw new BuildException(error);
218            }
219            ph = ph.getNext();
220         }while (ph!=null);
221     }
222
223
224
225     /**
226      * Installs this net as the given project's property helper.
227      * @param project this net's associated project
228      * @return <i>true</i> if net installed first time
229      * @.safety single
230      * @return <i>false</i> if already installed directly or indirectly
231      **/

232     public boolean install(Project project)
233     {
234         AntX.require_(project!=null,IAM_,"install- nonzro project");
235         setProject(project);
236         PropertyHelper current = PropertyHelper.getPropertyHelper(project);
237
238         verifyNotInChain_(current,project);
239
240         log("Installing...",Project.MSG_VERBOSE);
241         m_defImpl = current;
242         project.getReferences().put(ANT_HELPER_REFID,this);
243
244         AntX.verify_(PropertyHelper.getPropertyHelper(project)==this,
245                      IAM_,"install- installed properly");
246         return true;
247     }
248
249
250
251     /**
252      * Uninstalls this net as its project's property helper.
253      * Will reinstall the helper that was there when this net
254      * was installed.
255      * @param notInstalled [optional] error handler
256      * @throws BuildException if this net is not currently installed
257      **/

258     public void uninstall(ProblemHandler notInstalled)
259     {
260         Project P = getProjectNoNull();
261         PropertyHelper current = PropertyHelper.getPropertyHelper(P);
262         if (current==this) {
263             log("Uninstalling...",Project.MSG_VERBOSE);
264             P.getReferences().put(ANT_HELPER_REFID,m_defImpl);
265             m_defImpl = null;
266         } else if (current!=null) {
267             String JavaDoc error = AntX.uistrs().get("fixture.ph.not.instald",getName());
268             if (notInstalled!=null) {
269                 notInstalled.problem(error,Project.MSG_ERR);
270             }
271             throw new BuildException(error);
272         }
273     }
274
275
276
277     /**
278      * Installs a property definition if it isn't already
279      * installed from the command or control context.
280      **/

281     public synchronized boolean setProperty(String JavaDoc ns, String JavaDoc name,
282                                             Object JavaDoc value, boolean verbose)
283     {
284         AntX.require_(name!=null,IAM_,"setProperty- nonzro name");
285         boolean written = true;
286
287         if (getUserProperty(ns,name)==null) {
288             if (setPropertyHook(ns,name,value,false,false,false)) {
289                 if (verbose) {
290                     log("Set local hook property '"+name+
291                         "' -> "+value, Project.MSG_DEBUG);
292                 }
293             } else {
294                 Object JavaDoc old = m_allProperties.put(name,value);
295                 if (old!=null && old!=EMPTY) {
296                     log("Overwrote script property '"+name+"'");
297                 }
298                 else if (verbose) {
299                     log("Set script property '"+name+
300                         "' -> "+value, Project.MSG_DEBUG);
301                 }
302             }
303         } else {
304             written = false;
305             if (verbose) {
306                 log("Ignored script definition of '"+name+"'");
307             }
308         }
309         return written;
310     }
311
312
313
314     /**
315      * Installs a new property iff it is not already defined in
316      * any context. Never installs new properties to local hooks.
317      **/

318     public synchronized void setNewProperty(String JavaDoc ns, String JavaDoc name,
319                                             Object JavaDoc value)
320     {
321         if (getProperty(ns,name)!=null) {
322             log("Ignored new script definition of '"+name+"'");
323         } else {
324             m_allProperties.put(name,value);
325             log("Set script property '"+name+"' -> "+value,
326                 Project.MSG_DEBUG);
327         }
328     }
329
330
331
332     /**
333      * (Re)defines a command property. This method overrides
334      * unconditionally any existing command or general property
335      * definition.
336      **/

337     public synchronized void setUserProperty(String JavaDoc ns, String JavaDoc name,
338                                              Object JavaDoc value)
339     {
340         if (setPropertyHook(ns,name,value,false,true,false)) {
341             log("(Re)Set local hook CLI property '"+name+"' -> "+value);
342         }
343         else {
344             m_cliProperties.put(name,value);
345             m_allProperties.put(name,value);
346             log("(Re)Set CLI property '"+name+"' -> "+value);
347         }
348     }
349
350
351
352     /**
353      * (Re)defines a control property. This method overrides
354      * unconditionally any existing control, command, or general
355      * property definition. (Inherited properties are also
356      * considered command properties).
357      **/

358     public synchronized void setInheritedProperty(String JavaDoc ns, String JavaDoc name,
359                                                   Object JavaDoc value)
360     {
361         if (setPropertyHook(ns,name,value,true,false,false)) {
362             log("(Re)Set local hook CTRL property '"+name+"' -> "+value);
363         }
364         else {
365             m_controlProperties.put(name,value);
366             m_cliProperties.put(name,value);
367             m_allProperties.put(name,value);
368             log("(Re)Set CTRL property '"+name+"' -> "+value);
369         }
370     }
371
372
373
374     private Object JavaDoc readLocalURIs(String JavaDoc ns, String JavaDoc name, boolean userOnly)
375     {
376         Project p = getProjectNoNull();
377         if (FixtureExaminer.valueURIInterpreterInstalled(p)) {
378             return null;
379         }
380         if ((ns==null || ns.length()==0) && !userOnly) {
381             return FixtureExaminer.findValue(p,name,null);
382         }
383         return null;
384     }
385
386
387
388     /**
389      * Return a property's value from a custom task-installed
390      * hook or a non-property source if indicated. To return a
391      * a reference or a variable as a property preface your key
392      * with either "reference:" or "variable:".
393      * Will return <i>null</i> if no matching item found.
394      */

395     public Object JavaDoc getPropertyHook(String JavaDoc ns, String JavaDoc name, boolean userOnly)
396     {
397         Object JavaDoc o;
398
399         if (getOverride()!=null) {
400             o = getOverride().getPropertyHook(ns,name,userOnly);
401             if (o!=null) {
402                 return o;
403             }
404         }
405         return readLocalURIs(ns,name,userOnly);
406     }
407
408
409
410     /**
411      * Return a property's definition from any context. Will
412      * return <i>null</i> if item undefined <em>or</em>
413      * cleared.
414      */

415     public synchronized Object JavaDoc getProperty(String JavaDoc ns, String JavaDoc name)
416     {
417         Object JavaDoc o = getPropertyHook(ns,name,false);
418         return o==null ? getProperty0(ns,name) : o;
419     }
420
421
422
423     /**
424      * Returns a command or control property's definition. Will
425      * return <i>null</i> if item undefined <em>or</em> cleared.
426      */

427     public synchronized Object JavaDoc getUserProperty(String JavaDoc ns, String JavaDoc name)
428     {
429         Object JavaDoc o = getPropertyHook(ns,name,true);
430         return o==null ? getUserProperty0(ns,name) : o;
431     }
432
433
434
435     /**
436      * Returns a copy of this net's full collection of
437      * properties. Never returns <i>null</i>.
438      */

439     public synchronized Hashtable JavaDoc getProperties()
440     {
441         Hashtable JavaDoc copy = m_defImpl.getProperties();
442         copy.putAll(m_allProperties);
443         return copy;
444     }
445
446
447
448     /**
449      * Returns a copy of this net's command and control
450      * properties. Never returns <i>null</i>.
451      */

452     public synchronized Hashtable JavaDoc getUserProperties()
453     {
454         Hashtable JavaDoc copy = m_defImpl.getUserProperties();
455         copy.putAll(m_cliProperties);
456         return copy;
457     }
458
459
460
461     /**
462      * Copies this net's control properties to another project.
463      */

464     public synchronized void copyInheritedProperties(Project other)
465     {
466         AntX.require_(other!=getProject(),IAM_,"copyInherited- not same");
467
468         if (!m_controlProperties.isEmpty()) {
469             Iterator JavaDoc itr = m_controlProperties.entrySet().iterator();
470             while (itr.hasNext()) {
471                 Map.Entry JavaDoc mE = (Map.Entry JavaDoc)itr.next();
472                 String JavaDoc key = (String JavaDoc)mE.getKey();
473                 if (other.getUserProperty(key)==null) {
474                     other.setInheritedProperty(key,(String JavaDoc)mE.getValue());
475                 }
476             }
477         }
478         m_defImpl.copyInheritedProperties(other);//NB: won't override ours!
479
}
480
481
482
483     /**
484      * Copies this net's non-inherited command properties to
485      * another project.
486      */

487     public synchronized void copyUserProperties(Project other)
488     {
489         m_defImpl.copyUserProperties(other);
490         Iterator JavaDoc itr= m_cliProperties.entrySet().iterator();
491         while (itr.hasNext()) {
492             Map.Entry JavaDoc mE= (Map.Entry JavaDoc)itr.next();
493             if (!m_controlProperties.containsKey(mE.getKey())) {
494                 other.setUserProperty((String JavaDoc)mE.getKey(),(String JavaDoc)mE.getValue());
495             }
496         }
497     }
498
499
500
501     /**
502      * Returns a a copy of the properties captured by this
503      * net. Should be used <em>after</em> this net is uninstalled.
504      * @param filtered <i>true</i> if results should be filtered
505      * using seed values
506      * @param blocking <i>true</i> if the seed values should
507      * be removed; otherwise only seed values are returned.
508      * @since JWare/AntX 0.5
509      * @return final (optionally filtered) properties (non-null)
510      **/

511     public Map JavaDoc getFinalProperties(boolean filtered, boolean blocking)
512     {
513         Hashtable JavaDoc ht = new Hashtable JavaDoc(m_allProperties);
514         if (filtered) {
515             if (blocking) {
516                 ht.keySet().removeAll(m_rwProperties.keySet());
517             } else {
518                 ht.keySet().retainAll(m_rwProperties.keySet());
519                 Iterator JavaDoc itr= ht.values().iterator();
520                 while (itr.hasNext()) {
521                     if (itr.next()==EMPTY) {
522                         itr.remove();
523                     }
524                 }
525             }
526         }
527         return ht;
528     }
529
530
531
532     /**
533      * Returns this net's project ensuring that value has been
534      * defined.
535      * @throws IllegalStateException if this net has no project
536      */

537     private Project getProjectNoNull()
538     {
539         Project P = getProject();
540         AntX.verify_(P!=null,IAM_,"getProj- inited");
541         return P;
542     }
543
544
545     /**
546      * Internal command property getter. Synchronization must be
547      * done by public-facing API.
548      */

549     private Object JavaDoc getUserProperty0(String JavaDoc ns, String JavaDoc name)
550     {
551         if (name==null) {
552            return null;
553         }
554         Object JavaDoc o = m_cliProperties.get(name);
555         if (o==null) {
556             o = m_defImpl.getUserProperty(ns,name);
557         }
558         return o;
559     }
560
561
562     /**
563      * Internal general property getter. Synchronization must be
564      * done by public-facing API.
565      */

566     private Object JavaDoc getProperty0(String JavaDoc ns, String JavaDoc name)
567     {
568         if (name==null) {
569             return null;
570         }
571         Object JavaDoc o = m_allProperties.get(name);
572         if (o==null) {
573             o = m_defImpl.getProperty(ns,name);
574         } else {
575             if (o==EMPTY/*!*/) {//NB:allow for unset local properties!
576
o = null;
577             }
578         }
579         return o;
580     }
581
582
583     private void log(String JavaDoc msg, int noiselevel)
584     {
585         getProjectNoNull().log("PropertiesNet("+getName()+"): "+msg,
586                                noiselevel);
587     }
588
589
590     private void log(String JavaDoc msg)
591     {
592         getProjectNoNull().log("PropertiesNet("+getName()+"): "+msg,
593                                Project.MSG_VERBOSE);
594     }
595
596
597     private PropertyHelper getOverride()
598     {
599         return getNext();//stoopid name!
600
}
601
602
603     private static final String JavaDoc EMPTY= new String JavaDoc("");//NB:unique emptystring
604
private Project m_project;
605     private PropertyHelper m_defImpl;
606     private String JavaDoc m_nameImpl="n/d";
607     private Map JavaDoc m_allProperties = AntXFixture.newMap();//NB:public-API mt-safe
608
private Map JavaDoc m_cliProperties = AntXFixture.newMap();
609     private Map JavaDoc m_controlProperties = AntXFixture.newMap();
610     private Map JavaDoc m_rwProperties = Collections.EMPTY_MAP;//@since AntX-0.5
611
}
612
613
614 /* end-of-ProjectPropertiesNet.java */
615
Popular Tags