KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > solo > CopyReferenceTask


1 /**
2  * $Id: CopyReferenceTask.java 187 2007-03-25 17:59:16Z ssmc $
3  * Copyright 2002-2005,2007 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.1 of the License, or (at your option) any
9  * 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 (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://antxtras.sf.net/ EMAIL- jware[at]users[dot]sourceforge[dot]net
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.solo;
30
31 import java.lang.reflect.Method JavaDoc;
32
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.Location;
35 import org.apache.tools.ant.Project;
36
37 import com.idaremedia.antx.AntX;
38 import com.idaremedia.antx.AssertableTask;
39 import com.idaremedia.antx.apis.AntLibFriendly;
40 import com.idaremedia.antx.helpers.Empties;
41 import com.idaremedia.antx.parameters.FeedbackLevel;
42
43 /**
44  * Fixture configuration instruction to copy a reference within a single Project or
45  * from a parent Project to a child Project. Must be a Task derivative since expected to
46  * be nested inside TaskContainers (which only allow nested tasks).
47  * <p>
48  * <b>Example Usage:</b><pre>
49  * &lt;copyreference refid="default.buildnum" torefid="buildnum"/&gt;
50  * &lt;copyreference refid="default.buildnum" torefid="buildnum" overwrite="no"/&gt;
51  * &lt;copyreference refid="default.buildnum" torefid="buildnum" haltifexists="yes"/&gt;
52  * &lt;copyreference refid="allfilters" torefid="javafilters" shallow="yes"/&gt;
53  *
54  * -OR with flow-control tasks-
55  *
56  * &lt;callforeach targets="&#46;&#46;&#46;" &#46;&#46;&#46;&gt;
57  * &lt;reference refid="default.buildnum"/&gt;
58  * &lt;/callforeach&gt;
59  * </pre>
60  *
61  * @since JWare/AntX 0.3
62  * @author ssmc, &copy;2002-2005,2007 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
63  * @version 0.5
64  * @.safety single
65  * @.group api,helper
66  * @.pattern GoF.Adapter (when used with build-flowcontrol [call] tasks)
67  * @see CopyPropertyTask
68  **/

69
70 public final class CopyReferenceTask extends AssertableTask
71     implements AntLibFriendly
72 {
73     /**
74      * Initializes a new CopyReferenceTask adapter task.
75      **/

76     public CopyReferenceTask()
77     {
78         super(AntX.nopackage);
79     }
80
81
82     /**
83      * Set the source reference's identifier
84      * @param srcRefId existing reference (non-null).
85      **/

86     public void setRefId(String JavaDoc srcRefId)
87     {
88         require_(srcRefId!=null, "setRefId- nonzro id");
89         m_srcRefId = srcRefId;
90
91         if (m_dstRefId==null) {
92             m_dstRefId= srcRefId;
93         }
94     }
95
96
97     /**
98      * Returns the source reference's identifer.
99      * Returns <i>null</i> if never set.
100      **/

101     public String JavaDoc getRefId()
102     {
103         return m_srcRefId;
104     }
105
106
107     /**
108      * Set the target reference's identifier (non-null)
109      * @param dstRefId new reference (non-null)
110      * @see #setHaltIfExists
111      **/

112     public void setToRefId(String JavaDoc dstRefId)
113     {
114         require_(dstRefId!=null, "setRefToId- nonzro id");
115         m_dstRefId = dstRefId;
116     }
117
118
119     /**
120      * Returns the (new) target reference's identifer.
121      * Returns <i>null</i> if never set and source never
122      * set.
123      **/

124     public String JavaDoc getToRefId()
125     {
126         return m_dstRefId;
127     }
128
129
130     /**
131      * Sets if this task will generate a build error if the
132      * destination reference id already exists within its project.
133      * Trumps the 'overwrite' option.
134      * @param halt <i>true</i> to throw build exception
135      * @see #setToRefId
136      * @see #setOverwrite
137      **/

138     public void setHaltIfExists(boolean halt)
139     {
140         m_haltIfExists = halt;
141     }
142
143
144     /**
145      * Returns <i>true</i> if this task will generate a build error
146      * if the destination reference id already exists within its
147      * project. Defaults <i>false</i> (supports overwrites).
148      **/

149     public boolean isHaltIfExists()
150     {
151         return m_haltIfExists;
152     }
153
154
155     /**
156      * Sets if this task will overwrite an existing reference.
157      * This option is ignored if the 'haltiferror' option
158      * is turned on.
159      * @see #setHaltIfExists
160      * @param allowOverwrite <i>true</i> if can overwrite old reference
161      **/

162     public void setOverwrite(boolean allowOverwrite)
163     {
164         m_allowOverwrite = allowOverwrite;
165     }
166
167
168     /**
169      * Returns <i>true</i> if this task will overwrite an existing
170      * reference. Defaults <i>true</i>. Ignored if 'haltiferror'
171      * option is turned on.
172      **/

173     public boolean willAllowOverwrite()
174     {
175         return m_allowOverwrite;
176     }
177
178
179
180     /**
181      * Tells this copy to only copy the reference pointer; no cloning
182      * is necessary. Useful for moving a reference to another name.
183      * @param shallowCopy <i>true</i> to make copy shallow.
184      * @since JWare/AntX 0.5
185      **/

186     public void setShallow(boolean shallowCopy)
187     {
188         m_shallowCopy = shallowCopy;
189     }
190     
191     
192     
193     /**
194      * Returns <i>true</i> if this copy will be shallow (by reference
195      * only). Default <i>false</i> if never set explicitly.
196      * @since JWare/AntX 0.5
197      **/

198     public boolean willCopyShallow()
199     {
200         return m_shallowCopy;
201     }
202
203
204     /**
205      * Tells this task how much non-diagnostic feedback to generate.
206      * Really only has "loud" vs. "quiet-ish" interpretation. If
207      * set quiet, this task will not issue a warning if it hits a
208      * hard limit.
209      * @param level feedback level (non-null)
210      * @since JWare/AntX 0.5
211      **/

212     public void setFeedback(String JavaDoc level)
213     {
214         require_(level!=null,"setFeedback- nonzro level");
215         FeedbackLevel fbl = FeedbackLevel.from(level);
216         if (fbl==null) {
217             String JavaDoc e = getAntXMsg("task.illegal.param.value",
218                            getTaskName(), level,"feedback");
219             log(e, Project.MSG_ERR);
220             throw new BuildException(e, getLocation());
221         }
222         m_fbLevel = fbl;
223     }
224
225
226
227     /**
228      * Returns this task's assigned feedback level. Will return
229      * <i>null</i> by default.
230      * @since JWare/AntX 0.5
231      **/

232     public final FeedbackLevel getFeedbackLevel()
233     {
234         return m_fbLevel;
235     }
236
237
238
239     /**
240      * Tries to copy the source reference object to a new copy
241      * within this task's enclosing project.
242      * @throws BuildException if this task in incompletely defined,
243      * the source object cannot be cloned, or an object
244      * already exists with destination refid
245      **/

246     public void execute()
247     {
248         verifyCanExecute_("execute");
249
250         final Project P = getProject();
251         final boolean quiet = FeedbackLevel.isQuietish(m_fbLevel,true);
252         String JavaDoc src_refid = getRefId();
253         String JavaDoc dst_refid = getToRefId();
254
255         //NB: when executed as standalone the 'to' refid must be unique
256
if (src_refid.equals(dst_refid)) {
257             String JavaDoc ermsg = uistrs().get("task.needs.this.attr",getTaskName(),"torefid");
258             log(ermsg,Project.MSG_ERR);
259             throw new BuildException(ermsg,getLocation());
260         }
261
262         //NB: warn if about to stomp on some poor existing reference!
263
if (P.getReference(dst_refid)!=null) {
264             String JavaDoc msg = uistrs().get("task.warn.refid.exists",dst_refid);
265             if (isHaltIfExists()) {
266                 log(msg,Project.MSG_ERR);
267                 throw new BuildException(msg,getLocation());
268             }
269             if (!willAllowOverwrite()) {
270                 if (!quiet && m_fbLevel!=FeedbackLevel.NORMAL) {
271                     log(msg,Project.MSG_VERBOSE);
272                 }
273                 return;
274             }
275             if (!quiet) {
276                 log(msg,Project.MSG_WARN);
277             }
278         }
279
280         //NB: because the interface exists, doesn't mean it's implemented
281
// properly (ssmc)
282
Object JavaDoc src = P.getReference(src_refid);
283         Object JavaDoc dst = null;
284         try {
285             if (willCopyShallow()) {
286                 dst = src;
287             } else if (src instanceof String JavaDoc) {//FIXME:String-hack for now (ssmc)
288
dst = new String JavaDoc((String JavaDoc)src);
289             } else {
290                 Method JavaDoc cloneit = src.getClass().getMethod("clone", new Class JavaDoc[0]);
291                 dst = cloneit.invoke(src,Empties.EMPTY_CLASS_ARRAY);
292             }
293         } catch (Exception JavaDoc anyX) {
294             String JavaDoc ermsg = uistrs().get("task.bad.refid",src_refid,
295                                         "PUBLIC "+Cloneable JavaDoc.class.getName(),
296                                         src.getClass().getName());
297             log(ermsg,Project.MSG_ERR);
298             throw new BuildException(ermsg,anyX,getLocation());
299         }
300
301         log("Copying reference "+src_refid+" to "+dst_refid,Project.MSG_DEBUG);
302         if (quiet) {
303             P.getReferences().put(dst_refid, dst);
304         } else {
305             P.addReference(dst_refid, dst);
306         }
307         
308     }
309
310
311     /**
312      * Verifies that this task has at least its source reference
313      * identifier set.
314      * @throws BuildException if this task's source reference undefined
315      **/

316     public void verifyIsDefined()
317     {
318         if (getRefId()==null) {
319             String JavaDoc ermsg = uistrs().get("task.needs.this.attr",getTaskName(),"refid");
320             log(ermsg,Project.MSG_ERR);
321             throw new BuildException(ermsg,getLocation());
322         }
323     }
324
325
326     /**
327      * Verifies that this task refers to an existing project entity. If
328      * the project and/or location is not specified this task will use its
329      * own information.
330      * @param theProject [optional]project in which reference must exist
331      * @param theLocation [optional] location from which any error reported
332      * @param ofKind [optional] reference must be assignable as this class
333      * @throws BuildException if reference doesn't exist or is incompatible
334      **/

335     public void verifyExists(Project theProject, Location theLocation, Class JavaDoc ofKind)
336     {
337         verifyIsDefined();
338
339         if (theProject==null) {
340             theProject = getProject();
341             if (theProject==null) {
342                 throw new IllegalStateException JavaDoc("verifyExists- no project");
343             }
344         }
345         if (theLocation==null) {
346             theLocation = getLocation();
347         }
348
349         String JavaDoc error = null;
350
351         String JavaDoc refid = getRefId();
352
353         Object JavaDoc o = theProject.getReference(refid);
354         if (o==null) {
355             error = uistrs().get("task.missing.refid",refid);
356         } else if (ofKind!=null && !ofKind.isAssignableFrom(o.getClass())) {
357             if ((ofKind==Cloneable JavaDoc.class) && (o instanceof String JavaDoc)) {
358                 return;//FIXME:String-hack for now (ssmc)
359
}
360             error = uistrs().get("task.bad.refid",refid,ofKind.getName(),
361                                  o.getClass().getName());
362         }
363         if (error!=null) {
364             log(error,Project.MSG_ERR);
365             throw new BuildException(error,theLocation);
366         }
367     }
368
369
370     /**
371      * Verifies this task is completely defined, the source reference
372      * exists, and is publicly Cloneable.
373      * @throws BuildException if not valid
374      **/

375     protected void verifyCanExecute_(String JavaDoc calr)
376     {
377         verifyInProject_(calr);
378         
379         Class JavaDoc ofKind = Cloneable JavaDoc.class;
380         if (willCopyShallow()) {
381             ofKind = null;
382         }
383         verifyExists(null,null,ofKind);
384     }
385
386     private String JavaDoc m_srcRefId,m_dstRefId;
387     private boolean m_haltIfExists;//NB:false allow overwrites!
388
private boolean m_allowOverwrite=true;//NB:true allow overwrites!
389
private boolean m_shallowCopy;//NB:true=>no-cloning
390
private FeedbackLevel m_fbLevel=FeedbackLevel.NORMAL;//NB:=>overwrite noise
391
}
392
393 /* end-of-CopyReferenceTask.java */
394
Popular Tags