You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Ant.java 25 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  2. * Copyright 2000-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs;
  18. import java.io.File;
  19. import java.io.FileOutputStream;
  20. import java.io.IOException;
  21. import java.io.PrintStream;
  22. import java.lang.reflect.Method;
  23. import java.util.Enumeration;
  24. import java.util.Hashtable;
  25. import java.util.Iterator;
  26. import java.util.Vector;
  27. import java.util.Set;
  28. import java.util.HashSet;
  29. import org.apache.tools.ant.BuildException;
  30. import org.apache.tools.ant.BuildListener;
  31. import org.apache.tools.ant.DefaultLogger;
  32. import org.apache.tools.ant.Project;
  33. import org.apache.tools.ant.ProjectComponent;
  34. import org.apache.tools.ant.ProjectHelper;
  35. import org.apache.tools.ant.Target;
  36. import org.apache.tools.ant.Task;
  37. import org.apache.tools.ant.types.PropertySet;
  38. import org.apache.tools.ant.util.FileUtils;
  39. /**
  40. * Build a sub-project.
  41. *
  42. * <pre>
  43. * &lt;target name=&quot;foo&quot; depends=&quot;init&quot;&gt;
  44. * &lt;ant antfile=&quot;build.xml&quot; target=&quot;bar&quot; &gt;
  45. * &lt;property name=&quot;property1&quot; value=&quot;aaaaa&quot; /&gt;
  46. * &lt;property name=&quot;foo&quot; value=&quot;baz&quot; /&gt;
  47. * &lt;/ant&gt;</SPAN>
  48. * &lt;/target&gt;</SPAN>
  49. *
  50. * &lt;target name=&quot;bar&quot; depends=&quot;init&quot;&gt;
  51. * &lt;echo message=&quot;prop is ${property1} ${foo}&quot; /&gt;
  52. * &lt;/target&gt;
  53. * </pre>
  54. *
  55. *
  56. * @since Ant 1.1
  57. *
  58. * @ant.task category="control"
  59. */
  60. public class Ant extends Task {
  61. /** the basedir where is executed the build file */
  62. private File dir = null;
  63. /**
  64. * the build.xml file (can be absolute) in this case dir will be
  65. * ignored
  66. */
  67. private String antFile = null;
  68. /** the output */
  69. private String output = null;
  70. /** should we inherit properties from the parent ? */
  71. private boolean inheritAll = true;
  72. /** should we inherit references from the parent ? */
  73. private boolean inheritRefs = false;
  74. /** the properties to pass to the new project */
  75. private Vector properties = new Vector();
  76. /** the references to pass to the new project */
  77. private Vector references = new Vector();
  78. /** the temporary project created to run the build file */
  79. private Project newProject;
  80. /** The stream to which output is to be written. */
  81. private PrintStream out = null;
  82. /** the sets of properties to pass to the new project */
  83. private Vector propertySets = new Vector();
  84. /** the targets to call on the new project */
  85. private Vector targets = new Vector();
  86. /** whether the target attribute was specified **/
  87. private boolean targetAttributeSet = false;
  88. /**
  89. * If true, pass all properties to the new Ant project.
  90. * Defaults to true.
  91. * @param value if true pass all properties to the new Ant project.
  92. */
  93. public void setInheritAll(boolean value) {
  94. inheritAll = value;
  95. }
  96. /**
  97. * If true, pass all references to the new Ant project.
  98. * Defaults to false.
  99. * @param value if true, pass all references to the new Ant project
  100. */
  101. public void setInheritRefs(boolean value) {
  102. inheritRefs = value;
  103. }
  104. /**
  105. * Creates a Project instance for the project to call.
  106. */
  107. public void init() {
  108. newProject = new Project();
  109. newProject.setDefaultInputStream(getProject().getDefaultInputStream());
  110. newProject.setJavaVersionProperty();
  111. }
  112. /**
  113. * Called in execute or createProperty if newProject is null.
  114. *
  115. * <p>This can happen if the same instance of this task is run
  116. * twice as newProject is set to null at the end of execute (to
  117. * save memory and help the GC).</p>
  118. * <p>calls init() again</p>
  119. *
  120. */
  121. private void reinit() {
  122. init();
  123. }
  124. /**
  125. * Attaches the build listeners of the current project to the new
  126. * project, configures a possible logfile, transfers task and
  127. * data-type definitions, transfers properties (either all or just
  128. * the ones specified as user properties to the current project,
  129. * depending on inheritall), transfers the input handler.
  130. */
  131. private void initializeProject() {
  132. newProject.setInputHandler(getProject().getInputHandler());
  133. Iterator iter = getBuildListeners();
  134. while (iter.hasNext()) {
  135. newProject.addBuildListener((BuildListener) iter.next());
  136. }
  137. if (output != null) {
  138. File outfile = null;
  139. if (dir != null) {
  140. outfile = FileUtils.newFileUtils().resolveFile(dir, output);
  141. } else {
  142. outfile = getProject().resolveFile(output);
  143. }
  144. try {
  145. out = new PrintStream(new FileOutputStream(outfile));
  146. DefaultLogger logger = new DefaultLogger();
  147. logger.setMessageOutputLevel(Project.MSG_INFO);
  148. logger.setOutputPrintStream(out);
  149. logger.setErrorPrintStream(out);
  150. newProject.addBuildListener(logger);
  151. } catch (IOException ex) {
  152. log("Ant: Can't set output to " + output);
  153. }
  154. }
  155. getProject().initSubProject(newProject);
  156. // set user-defined properties
  157. getProject().copyUserProperties(newProject);
  158. if (!inheritAll) {
  159. // set Java built-in properties separately,
  160. // b/c we won't inherit them.
  161. newProject.setSystemProperties();
  162. } else {
  163. // set all properties from calling project
  164. addAlmostAll(getProject().getProperties());
  165. }
  166. Enumeration e = propertySets.elements();
  167. while (e.hasMoreElements()) {
  168. PropertySet ps = (PropertySet) e.nextElement();
  169. addAlmostAll(ps.getProperties());
  170. }
  171. }
  172. /**
  173. * Pass output sent to System.out to the new project.
  174. *
  175. * @param output a line of output
  176. * @since Ant 1.5
  177. */
  178. public void handleOutput(String output) {
  179. if (newProject != null) {
  180. newProject.demuxOutput(output, false);
  181. } else {
  182. super.handleOutput(output);
  183. }
  184. }
  185. /**
  186. * Process input into the ant task
  187. *
  188. * @param buffer the buffer into which data is to be read.
  189. * @param offset the offset into the buffer at which data is stored.
  190. * @param length the amount of data to read
  191. *
  192. * @return the number of bytes read
  193. *
  194. * @exception IOException if the data cannot be read
  195. *
  196. * @see Task#handleInput(byte[], int, int)
  197. *
  198. * @since Ant 1.6
  199. */
  200. public int handleInput(byte[] buffer, int offset, int length)
  201. throws IOException {
  202. if (newProject != null) {
  203. return newProject.demuxInput(buffer, offset, length);
  204. } else {
  205. return super.handleInput(buffer, offset, length);
  206. }
  207. }
  208. /**
  209. * Pass output sent to System.out to the new project.
  210. *
  211. * @param output The output to log. Should not be <code>null</code>.
  212. *
  213. * @since Ant 1.5.2
  214. */
  215. public void handleFlush(String output) {
  216. if (newProject != null) {
  217. newProject.demuxFlush(output, false);
  218. } else {
  219. super.handleFlush(output);
  220. }
  221. }
  222. /**
  223. * Pass output sent to System.err to the new project.
  224. *
  225. * @param output The error output to log. Should not be <code>null</code>.
  226. *
  227. * @since Ant 1.5
  228. */
  229. public void handleErrorOutput(String output) {
  230. if (newProject != null) {
  231. newProject.demuxOutput(output, true);
  232. } else {
  233. super.handleErrorOutput(output);
  234. }
  235. }
  236. /**
  237. * Pass output sent to System.err to the new project.
  238. *
  239. * @param output The error output to log. Should not be <code>null</code>.
  240. *
  241. * @since Ant 1.5.2
  242. */
  243. public void handleErrorFlush(String output) {
  244. if (newProject != null) {
  245. newProject.demuxFlush(output, true);
  246. } else {
  247. super.handleErrorFlush(output);
  248. }
  249. }
  250. /**
  251. * Do the execution.
  252. * @throws BuildException if a target tries to call itself
  253. * probably also if a BuildException is thrown by the new project
  254. */
  255. public void execute() throws BuildException {
  256. File savedDir = dir;
  257. String savedAntFile = antFile;
  258. Vector locals = new Vector(targets);
  259. try {
  260. if (newProject == null) {
  261. reinit();
  262. }
  263. if ((dir == null) && (inheritAll)) {
  264. dir = getProject().getBaseDir();
  265. }
  266. initializeProject();
  267. if (dir != null) {
  268. newProject.setBaseDir(dir);
  269. if (savedDir != null) {
  270. // has been set explicitly
  271. newProject.setInheritedProperty("basedir" ,
  272. dir.getAbsolutePath());
  273. }
  274. } else {
  275. dir = getProject().getBaseDir();
  276. }
  277. overrideProperties();
  278. if (antFile == null) {
  279. antFile = "build.xml";
  280. }
  281. File file = FileUtils.newFileUtils().resolveFile(dir, antFile);
  282. antFile = file.getAbsolutePath();
  283. log("calling target(s) "
  284. + ((locals.size() == 0) ? locals.toString() : "[default]")
  285. + " in build file " + antFile, Project.MSG_VERBOSE);
  286. newProject.setUserProperty("ant.file" , antFile);
  287. String thisAntFile = getProject().getProperty("ant.file");
  288. // Are we trying to call the target in which we are defined (or
  289. // the build file if this is a top level task)?
  290. if (thisAntFile != null
  291. && newProject.resolveFile(newProject.getProperty("ant.file"))
  292. .equals(getProject().resolveFile(thisAntFile))
  293. && getOwningTarget() != null) {
  294. if (getOwningTarget().getName().equals("")) {
  295. if (getTaskName().equals("antcall")) {
  296. throw new BuildException("antcall must not be used at"
  297. + " the top level.");
  298. } else {
  299. throw new BuildException(getTaskName() + " task at the"
  300. + " top level must not invoke"
  301. + " its own build file.");
  302. }
  303. }
  304. }
  305. try {
  306. ProjectHelper.configureProject(newProject, new File(antFile));
  307. } catch (BuildException ex) {
  308. throw ProjectHelper.addLocationToBuildException(
  309. ex, getLocation());
  310. }
  311. if (locals.size() == 0) {
  312. String defaultTarget = newProject.getDefaultTarget();
  313. if (defaultTarget != null) {
  314. locals.add(defaultTarget);
  315. }
  316. }
  317. if (newProject.getProperty("ant.file")
  318. .equals(getProject().getProperty("ant.file"))
  319. && getOwningTarget() != null) {
  320. String owningTargetName = getOwningTarget().getName();
  321. if (locals.contains(owningTargetName)) {
  322. throw new BuildException(getTaskName() + " task calling "
  323. + "its own parent target.");
  324. } else {
  325. boolean circular = false;
  326. for (Iterator it = locals.iterator(); !circular && it.hasNext();) {
  327. Target other = (Target)(getProject().getTargets().get(
  328. (String)(it.next())));
  329. circular |= (other != null
  330. && other.dependsOn(owningTargetName));
  331. }
  332. if (circular) {
  333. throw new BuildException(getTaskName()
  334. + " task calling a target"
  335. + " that depends on"
  336. + " its parent target \'"
  337. + owningTargetName
  338. + "\'.");
  339. }
  340. }
  341. }
  342. addReferences();
  343. if (locals.size() > 0 && !(locals.size() == 1 && locals.get(0) == "")) {
  344. Throwable t = null;
  345. try {
  346. log("Entering " + antFile + "...", Project.MSG_VERBOSE);
  347. newProject.fireSubBuildStarted();
  348. String[] nameArray =
  349. (String[])(locals.toArray(new String[locals.size()]));
  350. Hashtable targets = newProject.getTargets();
  351. Vector sortedTargets = newProject.topoSort(nameArray, targets);
  352. sortedTargets.setSize(sortedTargets.indexOf(targets.get(
  353. locals.lastElement())) + 1);
  354. newProject.executeSortedTargets(sortedTargets);
  355. } catch (BuildException ex) {
  356. t = ProjectHelper
  357. .addLocationToBuildException(ex, getLocation());
  358. throw (BuildException) t;
  359. } finally {
  360. log("Exiting " + antFile + ".", Project.MSG_VERBOSE);
  361. newProject.fireSubBuildFinished(t);
  362. }
  363. }
  364. } finally {
  365. // help the gc
  366. newProject = null;
  367. Enumeration e = properties.elements();
  368. while (e.hasMoreElements()) {
  369. Property p = (Property) e.nextElement();
  370. p.setProject(null);
  371. }
  372. if (output != null && out != null) {
  373. try {
  374. out.close();
  375. } catch (final Exception ex) {
  376. //ignore
  377. }
  378. }
  379. dir = savedDir;
  380. antFile = savedAntFile;
  381. }
  382. }
  383. /**
  384. * Override the properties in the new project with the one
  385. * explicitly defined as nested elements here.
  386. * @throws BuildException under unknown circumstances
  387. */
  388. private void overrideProperties() throws BuildException {
  389. // remove duplicate properties - last property wins
  390. // Needed for backward compatibility
  391. Set set = new HashSet();
  392. for (int i = properties.size() - 1; i >= 0; --i) {
  393. Property p = (Property) properties.get(i);
  394. if (p.getName() != null && !p.getName().equals("")) {
  395. if (set.contains(p.getName())) {
  396. properties.remove(i);
  397. } else {
  398. set.add(p.getName());
  399. }
  400. }
  401. }
  402. Enumeration e = properties.elements();
  403. while (e.hasMoreElements()) {
  404. Property p = (Property) e.nextElement();
  405. p.setProject(newProject);
  406. p.execute();
  407. }
  408. getProject().copyInheritedProperties(newProject);
  409. }
  410. /**
  411. * Add the references explicitly defined as nested elements to the
  412. * new project. Also copy over all references that don't override
  413. * existing references in the new project if inheritrefs has been
  414. * requested.
  415. * @throws BuildException if a reference does not have a refid
  416. */
  417. private void addReferences() throws BuildException {
  418. Hashtable thisReferences
  419. = (Hashtable) getProject().getReferences().clone();
  420. Hashtable newReferences = newProject.getReferences();
  421. Enumeration e;
  422. if (references.size() > 0) {
  423. for (e = references.elements(); e.hasMoreElements();) {
  424. Reference ref = (Reference) e.nextElement();
  425. String refid = ref.getRefId();
  426. if (refid == null) {
  427. throw new BuildException("the refid attribute is required"
  428. + " for reference elements");
  429. }
  430. if (!thisReferences.containsKey(refid)) {
  431. log("Parent project doesn't contain any reference '"
  432. + refid + "'",
  433. Project.MSG_WARN);
  434. continue;
  435. }
  436. thisReferences.remove(refid);
  437. String toRefid = ref.getToRefid();
  438. if (toRefid == null) {
  439. toRefid = refid;
  440. }
  441. copyReference(refid, toRefid);
  442. }
  443. }
  444. // Now add all references that are not defined in the
  445. // subproject, if inheritRefs is true
  446. if (inheritRefs) {
  447. for (e = thisReferences.keys(); e.hasMoreElements();) {
  448. String key = (String) e.nextElement();
  449. if (newReferences.containsKey(key)) {
  450. continue;
  451. }
  452. copyReference(key, key);
  453. }
  454. }
  455. }
  456. /**
  457. * Try to clone and reconfigure the object referenced by oldkey in
  458. * the parent project and add it to the new project with the key
  459. * newkey.
  460. *
  461. * <p>If we cannot clone it, copy the referenced object itself and
  462. * keep our fingers crossed.</p>
  463. */
  464. private void copyReference(String oldKey, String newKey) {
  465. Object orig = getProject().getReference(oldKey);
  466. if (orig == null) {
  467. log("No object referenced by " + oldKey + ". Can't copy to "
  468. + newKey,
  469. Project.MSG_WARN);
  470. return;
  471. }
  472. Class c = orig.getClass();
  473. Object copy = orig;
  474. try {
  475. Method cloneM = c.getMethod("clone", new Class[0]);
  476. if (cloneM != null) {
  477. copy = cloneM.invoke(orig, new Object[0]);
  478. log("Adding clone of reference " + oldKey, Project.MSG_DEBUG);
  479. }
  480. } catch (Exception e) {
  481. // not Clonable
  482. }
  483. if (copy instanceof ProjectComponent) {
  484. ((ProjectComponent) copy).setProject(newProject);
  485. } else {
  486. try {
  487. Method setProjectM =
  488. c.getMethod("setProject", new Class[] {Project.class});
  489. if (setProjectM != null) {
  490. setProjectM.invoke(copy, new Object[] {newProject});
  491. }
  492. } catch (NoSuchMethodException e) {
  493. // ignore this if the class being referenced does not have
  494. // a set project method.
  495. } catch (Exception e2) {
  496. String msg = "Error setting new project instance for "
  497. + "reference with id " + oldKey;
  498. throw new BuildException(msg, e2, getLocation());
  499. }
  500. }
  501. newProject.addReference(newKey, copy);
  502. }
  503. /**
  504. * Copies all properties from the given table to the new project -
  505. * omitting those that have already been set in the new project as
  506. * well as properties named basedir or ant.file.
  507. * @param props properties to copy to the new project
  508. * @since Ant 1.6
  509. */
  510. private void addAlmostAll(Hashtable props) {
  511. Enumeration e = props.keys();
  512. while (e.hasMoreElements()) {
  513. String key = e.nextElement().toString();
  514. if ("basedir".equals(key) || "ant.file".equals(key)) {
  515. // basedir and ant.file get special treatment in execute()
  516. continue;
  517. }
  518. String value = props.get(key).toString();
  519. // don't re-set user properties, avoid the warning message
  520. if (newProject.getProperty(key) == null) {
  521. // no user property
  522. newProject.setNewProperty(key, value);
  523. }
  524. }
  525. }
  526. /**
  527. * The directory to use as a base directory for the new Ant project.
  528. * Defaults to the current project's basedir, unless inheritall
  529. * has been set to false, in which case it doesn't have a default
  530. * value. This will override the basedir setting of the called project.
  531. * @param d new directory
  532. */
  533. public void setDir(File d) {
  534. this.dir = d;
  535. }
  536. /**
  537. * The build file to use.
  538. * Defaults to "build.xml". This file is expected to be a filename relative
  539. * to the dir attribute given.
  540. * @param s build file to use
  541. */
  542. public void setAntfile(String s) {
  543. // @note: it is a string and not a file to handle relative/absolute
  544. // otherwise a relative file will be resolved based on the current
  545. // basedir.
  546. this.antFile = s;
  547. }
  548. /**
  549. * The target of the new Ant project to execute.
  550. * Defaults to the new project's default target.
  551. * @param s target to invoke
  552. */
  553. public void setTarget(String s) {
  554. if (s.equals("")) {
  555. throw new BuildException("target attribute must not be empty");
  556. }
  557. targets.add(s);
  558. targetAttributeSet = true;
  559. }
  560. /**
  561. * Filename to write the output to.
  562. * This is relative to the value of the dir attribute
  563. * if it has been set or to the base directory of the
  564. * current project otherwise.
  565. * @param s file to which the output should go to
  566. */
  567. public void setOutput(String s) {
  568. this.output = s;
  569. }
  570. /**
  571. * Property to pass to the new project.
  572. * The property is passed as a 'user property'
  573. * @return new property created
  574. */
  575. public Property createProperty() {
  576. if (newProject == null) {
  577. reinit();
  578. }
  579. Property p = new Property(true, getProject());
  580. p.setProject(newProject);
  581. p.setTaskName("property");
  582. properties.addElement(p);
  583. return p;
  584. }
  585. /**
  586. * Reference element identifying a data type to carry
  587. * over to the new project.
  588. * @param r reference to add
  589. */
  590. public void addReference(Reference r) {
  591. references.addElement(r);
  592. }
  593. /**
  594. * Add a target to this Ant invocation.
  595. * @param target the <CODE>TargetElement</CODE> to add.
  596. * @since Ant 1.7
  597. */
  598. public void addConfiguredTarget(TargetElement t) {
  599. if (targetAttributeSet) {
  600. throw new BuildException(
  601. "nested target is incompatible with the target attribute");
  602. }
  603. String name = t.getName();
  604. if (name.equals("")) {
  605. throw new BuildException("target name must not be empty");
  606. }
  607. targets.add(name);
  608. }
  609. /**
  610. * Set of properties to pass to the new project.
  611. *
  612. * @param ps property set to add
  613. * @since Ant 1.6
  614. */
  615. public void addPropertyset(PropertySet ps) {
  616. propertySets.addElement(ps);
  617. }
  618. /**
  619. * @since Ant 1.6.2
  620. */
  621. private Iterator getBuildListeners() {
  622. return getProject().getBuildListeners().iterator();
  623. }
  624. /**
  625. * Helper class that implements the nested &lt;reference&gt;
  626. * element of &lt;ant&gt; and &lt;antcall&gt;.
  627. */
  628. public static class Reference
  629. extends org.apache.tools.ant.types.Reference {
  630. /** Creates a reference to be configured by Ant */
  631. public Reference() {
  632. super();
  633. }
  634. private String targetid = null;
  635. /**
  636. * Set the id that this reference to be stored under in the
  637. * new project.
  638. *
  639. * @param targetid the id under which this reference will be passed to
  640. * the new project */
  641. public void setToRefid(String targetid) {
  642. this.targetid = targetid;
  643. }
  644. /**
  645. * Get the id under which this reference will be stored in the new
  646. * project
  647. *
  648. * @return the id of the reference in the new project.
  649. */
  650. public String getToRefid() {
  651. return targetid;
  652. }
  653. }
  654. /**
  655. * Helper class that implements the nested &lt;target&gt;
  656. * element of &lt;ant&gt; and &lt;antcall&gt;.
  657. * @since Ant 1.7
  658. */
  659. public static class TargetElement {
  660. private String name;
  661. /**
  662. * Default constructor.
  663. */
  664. public TargetElement() {}
  665. /**
  666. * Set the name of this TargetElement.
  667. * @param name the <CODE>String</CODE> target name.
  668. */
  669. public void setName(String name) {
  670. this.name = name;
  671. }
  672. /**
  673. * Get the name of this TargetElement.
  674. * @return <CODE>String</CODE>.
  675. */
  676. public String getName() {
  677. return name;
  678. }
  679. }
  680. }