1. /*
  2. * Copyright 2001-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.optional.starteam;
  18. import com.starbase.starteam.Folder;
  19. import com.starbase.starteam.Label;
  20. import com.starbase.starteam.PropertyNames;
  21. import com.starbase.starteam.StarTeamFinder;
  22. import com.starbase.starteam.View;
  23. import com.starbase.starteam.ViewConfiguration;
  24. import com.starbase.util.OLEDate;
  25. import java.text.ParseException;
  26. import java.text.SimpleDateFormat;
  27. import java.util.Date;
  28. import java.util.Hashtable;
  29. import java.util.StringTokenizer;
  30. import org.apache.tools.ant.BuildException;
  31. import org.apache.tools.ant.util.DateUtils;
  32. import org.apache.tools.ant.DirectoryScanner;
  33. import org.apache.tools.ant.Project;
  34. /**
  35. * TreeBasedTask.java
  36. * This abstract class is the base for any tasks that are tree-based, that
  37. * is, for tasks which iterate over a tree of folders in StarTeam which
  38. * is reflected in a tree of folder the local machine.
  39. *
  40. * This class provides the tree-iteration functionality. Derived classes
  41. * will implement their specific task functionality by the visitor pattern,
  42. * specifically by implementing the method
  43. * <code>visit(Folder rootStarteamFolder, java.io.File rootLocalFolder)</code>
  44. *
  45. * Created: Sat Dec 15 16:55:19 2001
  46. *
  47. * @version 1.0
  48. * @see <A HREF="http://www.starbase.com/">StarBase Web Site</A>
  49. */
  50. public abstract class TreeBasedTask extends StarTeamTask {
  51. ///////////////////////////////////////////////////////////////
  52. // default values for attributes.
  53. ///////////////////////////////////////////////////////////////
  54. /**
  55. * This constant sets the filter to include all files. This default has
  56. * the same result as <CODE>setIncludes("*")</CODE>.
  57. *
  58. * @see #getIncludes()
  59. * @see #setIncludes(String includes)
  60. */
  61. public static final String DEFAULT_INCLUDESETTING = "*";
  62. /**
  63. * This disables the exclude filter by default. In other words, no files
  64. * are excluded. This setting is equivalent to
  65. * <CODE>setExcludes(null)</CODE>.
  66. *
  67. * @see #getExcludes()
  68. * @see #setExcludes(String excludes)
  69. */
  70. public static final String DEFAULT_EXCLUDESETTING = null;
  71. //ATTRIBUTES settable from ant.
  72. /**
  73. * The root folder of the operation in StarTeam.
  74. */
  75. private String rootStarteamFolder = "/";
  76. /**
  77. * The local folder corresponding to starteamFolder. If not specified
  78. * the Star Team default folder will be used.
  79. */
  80. private String rootLocalFolder = null;
  81. /**
  82. * All files that fit this pattern are checked out.
  83. */
  84. private String includes = DEFAULT_INCLUDESETTING;
  85. /**
  86. * All files fitting this pattern are ignored.
  87. */
  88. private String excludes = DEFAULT_EXCLUDESETTING;
  89. /**
  90. * StarTeam label on which to perform task.
  91. */
  92. private String label = null;
  93. /**
  94. * Set recursion to false to check out files in only the given folder
  95. * and not in its subfolders.
  96. */
  97. private boolean recursive = true;
  98. /**
  99. * Set preloadFileInformation to true to load all file information from the server
  100. * at once. Increases performance significantly for projects with many files and/or folders.
  101. */
  102. private boolean preloadFileInformation = true;
  103. /**
  104. * If forced set to true, files in the target directory will
  105. * be processed regardless of status in the repository.
  106. * Usually this should be true if rootlocalfolder is set
  107. * because status will be relative to the default folder, not
  108. * to the one being processed.
  109. */
  110. private boolean forced = false;
  111. private Label labelInUse = null;
  112. /**
  113. * holder for the asofdate attribute
  114. */
  115. private String asOfDate = null;
  116. /**
  117. * holder for the asofdateformat attribute
  118. */
  119. private String asOfDateFormat = null;
  120. ///////////////////////////////////////////////////////////////
  121. // GET/SET methods.
  122. // Setters, of course are where ant user passes in values.
  123. ///////////////////////////////////////////////////////////////
  124. /**
  125. * Set the root of the subtree in the StarTeam repository from which to
  126. * work; optional. Defaults to the root folder of the view ('/').
  127. * @param rootStarteamFolder the root folder
  128. */
  129. public void setRootStarteamFolder(String rootStarteamFolder) {
  130. this.rootStarteamFolder = rootStarteamFolder;
  131. }
  132. /**
  133. * returns the root folder in the Starteam repository
  134. * used for this operation
  135. * @return the root folder in use
  136. */
  137. public String getRootStarteamFolder() {
  138. return this.rootStarteamFolder;
  139. }
  140. /**
  141. * Set the local folder that will be the root of the tree
  142. * to which files are checked out; optional.
  143. * If this is not supplied, then the StarTeam "default folder"
  144. * associated with <tt>rootstarteamfolder</tt> is used.
  145. *
  146. * @param rootLocalFolder
  147. * the local folder that will mirror
  148. * this.rootStarteamFolder
  149. *
  150. * @see rootLocalFolder
  151. */
  152. public void setRootLocalFolder(String rootLocalFolder) {
  153. this.rootLocalFolder = rootLocalFolder;
  154. }
  155. /**
  156. * Returns the local folder specified by the user,
  157. * corresponding to the starteam folder for this operation
  158. * or null if not specified.
  159. *
  160. * @return the local folder that mirrors this.rootStarteamFolder
  161. * @see rootLocalFolder
  162. */
  163. public String getRootLocalFolder() {
  164. return this.rootLocalFolder;
  165. }
  166. /**
  167. * Declare files to include using standard <tt>includes</tt> patterns; optional.
  168. * @param includes A string of filter patterns to include. Separate the
  169. * patterns by spaces.
  170. * @see #getIncludes()
  171. * @see #setExcludes(String excludes)
  172. * @see #getExcludes()
  173. */
  174. public void setIncludes(String includes) {
  175. this.includes = includes;
  176. }
  177. /**
  178. * Gets the patterns from the include filter. Rather that duplicate the
  179. * details of AntStarTeamCheckOut's filtering here, refer to these
  180. * links:
  181. *
  182. * @return A string of filter patterns separated by spaces.
  183. * @see #setIncludes(String includes)
  184. * @see #setExcludes(String excludes)
  185. * @see #getExcludes()
  186. */
  187. public String getIncludes() {
  188. return includes;
  189. }
  190. /**
  191. * if excludes have been specified, emit the list to the log
  192. */
  193. protected void logIncludes() {
  194. if (this.DEFAULT_INCLUDESETTING != this.includes) {
  195. log(" Includes specified: " + this.includes);
  196. }
  197. }
  198. /**
  199. * Declare files to exclude using standard <tt>excludes</tt> patterns; optional.
  200. * When filtering files, AntStarTeamCheckOut
  201. * uses an unmodified version of <CODE>DirectoryScanner</CODE>'s
  202. * <CODE>match</CODE> method, so here are the patterns straight from the
  203. * Ant source code:
  204. * <BR><BR>
  205. * Matches a string against a pattern. The pattern contains two special
  206. * characters:
  207. * <BR>'*' which means zero or more characters,
  208. * <BR>'?' which means one and only one character.
  209. * <BR><BR>
  210. * For example, if you want to check out all files except .XML and
  211. * .HTML files, you would put the following line in your program:
  212. * <CODE>setExcludes("*.XML,*.HTML");</CODE>
  213. * Finally, note that filters have no effect on the <B>directories</B>
  214. * that are scanned; you could not skip over all files in directories
  215. * whose names begin with "project," for instance.
  216. * <BR><BR>
  217. * Treatment of overlapping inlcudes and excludes: To give a simplistic
  218. * example suppose that you set your include filter to "*.htm *.html"
  219. * and your exclude filter to "index.*". What happens to index.html?
  220. * AntStarTeamCheckOut will not check out index.html, as it matches an
  221. * exclude filter ("index.*"), even though it matches the include
  222. * filter, as well.
  223. * <BR><BR>
  224. * Please also read the following sections before using filters:
  225. *
  226. * @param excludes A string of filter patterns to exclude. Separate the
  227. * patterns by spaces.
  228. * @see #setIncludes(String includes)
  229. * @see #getIncludes()
  230. * @see #getExcludes()
  231. */
  232. public void setExcludes(String excludes) {
  233. this.excludes = excludes;
  234. }
  235. /**
  236. * Gets the patterns from the exclude filter. Rather that duplicate the
  237. * details of AntStarTeanCheckOut's filtering here, refer to these
  238. * links:
  239. *
  240. * @return A string of filter patterns separated by spaces.
  241. * @see #setExcludes(String excludes)
  242. * @see #setIncludes(String includes)
  243. * @see #getIncludes()
  244. */
  245. public String getExcludes() {
  246. return excludes;
  247. }
  248. /**
  249. * if excludes have been specified, emit the list to the log
  250. */
  251. protected void logExcludes() {
  252. if (this.DEFAULT_EXCLUDESETTING != this.excludes) {
  253. log(" Excludes specified: " + this.excludes);
  254. }
  255. }
  256. /**
  257. * protected function to allow subclasses to set the label (or not).
  258. * sets the StarTeam label
  259. *
  260. * @param label name of the StarTeam label to be set
  261. */
  262. protected void _setLabel(String label) {
  263. if (null != label) {
  264. label = label.trim();
  265. if (label.length() > 0) {
  266. this.label = label;
  267. }
  268. }
  269. }
  270. /**
  271. * non-public method callable only by derived classes that implement
  272. * setAsOfDate (so that derived tasks that do not accept this
  273. * parameter will fail if user attempts to use it.
  274. *
  275. * @param asOfDate asOfDate entered by user.
  276. * @since Ant 1.6
  277. */
  278. protected void _setAsOfDate(String asOfDate) {
  279. if (asOfDate != null && asOfDate.length() > 0) {
  280. this.asOfDate = asOfDate;
  281. }
  282. }
  283. /**
  284. * non-public method callable only by derived classes that implement
  285. * setAsOfDateFormat (so that derived tasks that do not accept this
  286. * parameter will fail if user attempts to use it.
  287. *
  288. * @param asOfDateFormat asOfDate format entered by user.
  289. * @since Ant 1.6
  290. */
  291. protected void _setAsOfDateFormat(String asOfDateFormat) {
  292. if (asOfDateFormat != null && asOfDateFormat.length() > 0) {
  293. this.asOfDateFormat = asOfDateFormat;
  294. }
  295. }
  296. /**
  297. * return the asOfDate entered by the user for internal use by derived
  298. * classes.
  299. *
  300. * @return the asOfDate entered by the user
  301. * @since Ant 1.6
  302. */
  303. protected String getAsOfDate() {
  304. return this.asOfDate;
  305. }
  306. /**
  307. * If an asofDate parameter has been supplied by the user return a
  308. * StarTeam view based on the configuration of the StarTeam view
  309. * specified the user as of the date specified in the parameter.
  310. * If no asofDate has been specified, return null.
  311. *
  312. * This method is meant to be called from within implementations of the
  313. * <code>createSnapshotView</code> abstract method.
  314. *
  315. * @param raw the raw view to be configured as of the supplied date
  316. *
  317. * @return the view as configured.
  318. * @exception BuildException
  319. * thrown if the date is not parsable by the default or
  320. * supplied format patterns.
  321. * @since Ant 1.6
  322. */
  323. protected View getViewConfiguredByDate(View raw) throws BuildException {
  324. if (this.asOfDate == null) {
  325. return null;
  326. }
  327. Date asOfDate = null;
  328. SimpleDateFormat fmt = null;
  329. if (this.asOfDateFormat != null) {
  330. fmt = new SimpleDateFormat(this.asOfDateFormat);
  331. try {
  332. asOfDate = fmt.parse(this.asOfDate);
  333. }
  334. catch (ParseException px)
  335. {
  336. throw new BuildException("AsOfDate "
  337. + this.asOfDate
  338. + " not parsable by supplied format "
  339. + this.asOfDateFormat);
  340. }
  341. } else {
  342. try {
  343. asOfDate = DateUtils.parseIso8601DateTimeOrDate(
  344. this.asOfDate);
  345. } catch (ParseException px) {
  346. throw new BuildException("AsOfDate "
  347. + this.asOfDate
  348. + " not parsable by default"
  349. + " ISO8601 formats");
  350. }
  351. }
  352. return new View(raw, ViewConfiguration.createFromTime(
  353. new OLEDate(asOfDate)));
  354. }
  355. /**
  356. * return the label passed to the task by the user as a string
  357. *
  358. * @return the label passed to the task by the user as a string
  359. */
  360. protected String getLabel() {
  361. return this.label;
  362. }
  363. /**
  364. * Get the value of recursive.
  365. * @return value of recursive.
  366. */
  367. public boolean isRecursive() {
  368. return this.recursive;
  369. }
  370. /**
  371. * Flag to set to include files in subfolders in the operation; optional,
  372. * default true.
  373. * @param v Value to assign to recursive.
  374. */
  375. public void setRecursive(boolean v) {
  376. this.recursive = v;
  377. }
  378. /**
  379. * Get the value of preloadFileInformation.
  380. * @return value of preloadFileInformation.
  381. */
  382. public boolean isPreloadFileInformation() {
  383. return this.preloadFileInformation;
  384. }
  385. /**
  386. * Flag to set to preload file information from the server; optional,
  387. * default true.
  388. * Increases performance significantly for projects with many files
  389. * and/or folders.
  390. * @param v Value to assign to preloadFileInformation.
  391. */
  392. public void setPreloadFileInformation(boolean v) {
  393. this.preloadFileInformation = v;
  394. }
  395. /**
  396. * Get the value of forced.
  397. * @return value of forced.
  398. */
  399. public boolean isForced() {
  400. return this.forced;
  401. }
  402. /**
  403. * Flag to force actions regardless of the status
  404. * that StarTeam is maintaining for the file; optional, default false.
  405. * If <tt>rootlocalfolder</tt> is set then
  406. * this should be set "true" as otherwise the checkout will be based on statuses
  407. * which do not relate to the target folder.
  408. * @param v Value to assign to forced.
  409. */
  410. public void setForced(boolean v) {
  411. this.forced = v;
  412. }
  413. /**
  414. * returns true if a label has been specified and it is a view label.
  415. *
  416. * @return true if a label has been specified and it is a view label
  417. */
  418. protected boolean isUsingViewLabel() {
  419. return null != this.labelInUse && this.labelInUse.isViewLabel();
  420. }
  421. /**
  422. * returns true if a label has been specified and it is a revision label.
  423. *
  424. * @return true if a label has been specified and it is a revision label
  425. */
  426. protected boolean isUsingRevisionLabel() {
  427. return null != this.labelInUse && this.labelInUse.isRevisionLabel();
  428. }
  429. /**
  430. * returns the label being used
  431. *
  432. * @return the label being used
  433. */
  434. protected Label getLabelInUse() {
  435. return this.labelInUse;
  436. }
  437. /**
  438. * show the label in the log and its type.
  439. */
  440. protected void logLabel() {
  441. if (this.isUsingViewLabel()) {
  442. log(" Using view label " + getLabel());
  443. } else if (this.isUsingRevisionLabel()) {
  444. log(" Using revision label " + getLabel());
  445. }
  446. }
  447. /**
  448. * show the asofDate in the log
  449. * @since Ant 1.6
  450. */
  451. protected void logAsOfDate() {
  452. if (null != this.asOfDate) {
  453. log(" Using view as of date " + getAsOfDate());
  454. }
  455. }
  456. ///////////////////////////////////////////////////////////////
  457. // INCLUDE-EXCLUDE processing
  458. ///////////////////////////////////////////////////////////////
  459. /**
  460. * Look if the file should be processed by the task.
  461. * Don't process it if it fits no include filters or if
  462. * it fits an exclude filter.
  463. *
  464. * @param pName the item name to look for being included.
  465. *
  466. * @return whether the file should be processed or not.
  467. */
  468. protected boolean shouldProcess(String pName) {
  469. boolean includeIt = matchPatterns(getIncludes(), pName);
  470. boolean excludeIt = matchPatterns(getExcludes(), pName);
  471. return (includeIt && !excludeIt);
  472. }
  473. /**
  474. * Convenience method to see if a string match a one pattern
  475. * in given set of space-separated patterns.
  476. * @param patterns the space-separated list of patterns.
  477. * @param pName the name to look for matching.
  478. * @return whether the name match at least one pattern.
  479. */
  480. protected boolean matchPatterns(String patterns, String pName) {
  481. if (patterns == null) {
  482. return false;
  483. }
  484. StringTokenizer exStr = new StringTokenizer(patterns, ",");
  485. while (exStr.hasMoreTokens()) {
  486. if (DirectoryScanner.match(exStr.nextToken(), pName)) {
  487. return true;
  488. }
  489. }
  490. return false;
  491. }
  492. /**
  493. * Finds and opens the root starteam folder of the operation specified
  494. * by this task. This will be one of the following cases:
  495. *
  496. * @return Starteam's root folder for the operation.
  497. * @exception BuildException
  498. * if the root folder cannot be found in the repository
  499. */
  500. private final Folder configureRootStarteamFolder()
  501. throws BuildException {
  502. Folder starteamrootfolder = null;
  503. try {
  504. // no root local mapping has been specified.
  505. View snapshot = openView();
  506. // find the starteam folder specified to be the root of the
  507. // operation. Throw if it can't be found.
  508. starteamrootfolder =
  509. StarTeamFinder.findFolder(snapshot.getRootFolder(),
  510. this.rootStarteamFolder);
  511. if (this.isPreloadFileInformation()) {
  512. PropertyNames pn = getServer().getPropertyNames();
  513. String[] props = new String[] {pn.FILE_NAME, pn.FILE_PATH,
  514. pn.FILE_STATUS, pn.MODIFIED_TIME,
  515. pn.FILE_FILE_TIME_AT_CHECKIN,
  516. pn.MODIFIED_USER_ID, pn.FILE_SIZE};
  517. int depth = this.isRecursive() ? -1 : 0;
  518. starteamrootfolder.populateNow(getServer().getTypeNames().FILE,
  519. props, depth);
  520. }
  521. } catch (BuildException e) {
  522. throw e;
  523. } catch (Exception e) {
  524. StringBuffer msg = new StringBuffer("Unable to find root folder ")
  525. .append(this.rootStarteamFolder)
  526. .append(" in repository at ")
  527. .append(getURL());
  528. if (this.label != null) {
  529. msg.append(" using specified label ").append(this.label);
  530. }
  531. if (this.asOfDate != null) {
  532. msg.append(" as of specified date ")
  533. .append(this.asOfDate);
  534. }
  535. throw new BuildException(msg.toString(), e);
  536. }
  537. if (null == starteamrootfolder) {
  538. throw new BuildException("Unable to find root folder "
  539. + this.rootStarteamFolder + " in repository at " + getURL());
  540. }
  541. return starteamrootfolder;
  542. }
  543. /**
  544. * Returns the local folder mapped to the given StarTeam root folder
  545. * of the operation. There are two cases here, depending on whether
  546. * <code>rootLocalFolder</code> is defined.
  547. * If <code>rootLocalFolder</code> is defined, it will be used to
  548. * establish a root mapping. Otherwise, the repository's default root
  549. * folder will be used.
  550. *
  551. * @param starteamrootfolder
  552. * root Starteam folder initialized for the operation
  553. *
  554. * @return the local folder corresponding to the root Starteam folder.
  555. * @see findRootStarteamFolder
  556. */
  557. private final java.io.File getLocalRootMapping(Folder starteamrootfolder) {
  558. // set the local folder.
  559. String localrootfolder;
  560. if (null != this.rootLocalFolder) {
  561. localrootfolder = rootLocalFolder;
  562. } else {
  563. // either use default path or root local mapping,
  564. // which is now embedded in the root folder
  565. localrootfolder = starteamrootfolder.getPathFragment();
  566. }
  567. return new java.io.File(localrootfolder);
  568. }
  569. /**
  570. * extenders should emit to the log an entry describing the parameters
  571. * that will be used by this operation.
  572. *
  573. * @param starteamrootFolder
  574. * root folder in StarTeam for the operation
  575. * @param targetrootFolder
  576. * root local folder for the operation (whether specified by the user or not.
  577. */
  578. protected abstract void logOperationDescription(
  579. Folder starteamrootFolder, java.io.File targetrootFolder);
  580. /**
  581. * This method does the work of opening the supplied Starteam view and
  582. * calling the <code>visit()</code> method to perform the task.
  583. * Derived classes can customize the called methods
  584. * <code>testPreconditions()</code> and <code>visit()</code>.
  585. *
  586. * @exception BuildException if any error occurs in the processing
  587. * @see <code>testPreconditions()</code>
  588. * @see <code>visit()</code>
  589. */
  590. public final void execute() throws BuildException {
  591. try {
  592. Folder starteamrootfolder = configureRootStarteamFolder();
  593. // set the local folder.
  594. java.io.File localrootfolder =
  595. getLocalRootMapping(starteamrootfolder);
  596. testPreconditions();
  597. // Tell user what he is doing
  598. logOperationDescription(starteamrootfolder, localrootfolder);
  599. // Inspect everything in the root folder and then recursively
  600. visit(starteamrootfolder, localrootfolder);
  601. } catch (Exception e) {
  602. throw new BuildException(e);
  603. } finally {
  604. disconnectFromServer();
  605. }
  606. }
  607. private void findLabel(View v) throws BuildException {
  608. Label[] allLabels = v.getLabels();
  609. for (int i = 0; i < allLabels.length; i++) {
  610. Label stLabel = allLabels[i];
  611. log("checking label " + stLabel.getName(), Project.MSG_DEBUG);
  612. if (stLabel != null && !stLabel.isDeleted() && stLabel.getName().equals(this.label)) {
  613. if (!stLabel.isRevisionLabel() && !stLabel.isViewLabel()) {
  614. throw new BuildException("Unexpected label type.");
  615. }
  616. log("using label " + stLabel.getName(), Project.MSG_VERBOSE);
  617. this.labelInUse = stLabel;
  618. return;
  619. }
  620. }
  621. throw new BuildException("Error: label "
  622. + this.label
  623. + " does not exist in view "
  624. + v.getFullName());
  625. }
  626. /**
  627. * Helper method calls on the StarTeam API to retrieve an ID number
  628. * for the specified view, corresponding to this.label.
  629. * @param v the <code>View</code> in which to search for <code>this.label</code>
  630. * @return the ID number corresponding to <code>this.label</code> or -1 if
  631. * no label was provided.
  632. * @exception BuildException if <code>this.label</code> does not correspond
  633. * to any label in the supplied view
  634. */
  635. protected int getLabelID(View v) throws BuildException {
  636. if (null != this.label) {
  637. findLabel(v);
  638. return this.labelInUse.getID();
  639. }
  640. return -1;
  641. }
  642. protected int getIDofLabelInUse() {
  643. if (null != this.labelInUse) {
  644. return this.labelInUse.getID();
  645. }
  646. return -1;
  647. }
  648. /**
  649. * Derived classes must override this class to define actual processing
  650. * to be performed on each folder in the tree defined for the task
  651. *
  652. * @param rootStarteamFolder
  653. * the StarTeam folderto be visited
  654. * @param rootLocalFolder
  655. * the local mapping of rootStarteamFolder
  656. *
  657. * @exception BuildException
  658. */
  659. protected abstract void visit(Folder rootStarteamFolder,
  660. java.io.File rootLocalFolder)
  661. throws BuildException;
  662. /**
  663. * Derived classes must override this method to define tests for
  664. * any preconditons required by the task. This method is called at
  665. * the beginning of the execute() method.
  666. *
  667. * @exception BuildException throw if any fatal error exists in the
  668. * parameters supplied. If there is a non-fatal condition, just writing
  669. * to the log may be appropriate.
  670. * @see <code>execute()</code>
  671. */
  672. protected abstract void testPreconditions() throws BuildException;
  673. /**
  674. * Return the full repository path name of a file. Surprisingly there's
  675. * no method in com.starbase.starteam.File to provide this.
  676. *
  677. * @param remotefile the Star Team file whose path is to be returned
  678. *
  679. * @return the full repository path name of a file.
  680. */
  681. public static String getFullRepositoryPath(
  682. com.starbase.starteam.File remotefile) {
  683. StringBuffer sb = new StringBuffer();
  684. sb.append(remotefile.getParentFolderHierarchy())
  685. .append(remotefile.getName());
  686. return sb.toString();
  687. }
  688. /**
  689. * This class implements a map of existing local files to possibly
  690. * existing repository files. The map is created by a TreeBasedTask
  691. * upon recursing into a directory. Each local item is mapped to an
  692. * unattached StarTeam object of the proper type, File->File and
  693. * Directory->Folder.
  694. *
  695. * As the TreeBased does its work, it deletes from the map all items
  696. * it has processed.
  697. *
  698. * When the TreeBased task processes all the items from the repository,
  699. * whatever items left in the UnmatchedFileMap are uncontrolled items
  700. * and can be processed as appropriate to the task. In the case of
  701. * Checkouts, they can be optionally deleted from the local tree. In the
  702. * case of Checkins they can optionally be added to the repository.
  703. */
  704. protected abstract class UnmatchedFileMap extends Hashtable {
  705. /**
  706. * initializes the UnmatchedFileMap with entries from the local folder
  707. * These will be mapped to the corresponding StarTeam entry even though
  708. * it will not, in fact, exist in the repository. But through it, it
  709. * can be added, listed, etc.
  710. *
  711. * @param localFolder
  712. * the local folder from which the mappings will be made.
  713. * @param remoteFolder
  714. * the corresponding StarTeam folder which will be processed.
  715. */
  716. UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) {
  717. if (!localFolder.exists()) {
  718. return this;
  719. }
  720. String[] localFiles = localFolder.list();
  721. for (int i = 0; i < localFiles.length; i++) {
  722. String fn = localFiles[i];
  723. java.io.File localFile =
  724. new java.io.File(localFolder, localFiles[i]).getAbsoluteFile();
  725. log("adding " + localFile + " to UnmatchedFileMap",
  726. Project.MSG_DEBUG);
  727. if (localFile.isDirectory()) {
  728. this.put(localFile, new Folder(remoteFolder, fn, fn));
  729. } else {
  730. com.starbase.starteam.File remoteFile =
  731. new com.starbase.starteam.File(remoteFolder);
  732. remoteFile.setName(fn);
  733. this.put(localFile, remoteFile);
  734. }
  735. }
  736. return this;
  737. }
  738. /**
  739. * remove an item found to be controlled from the map.
  740. *
  741. * @param localFile the local item found to be controlled.
  742. */
  743. void removeControlledItem(java.io.File localFile) {
  744. if (isActive()) {
  745. log("removing processed " + localFile.getAbsoluteFile()
  746. + " from UnmatchedFileMap", Project.MSG_DEBUG);
  747. this.remove(localFile.getAbsoluteFile());
  748. }
  749. }
  750. /**
  751. * override will perform the action appropriate for its task to perform
  752. * on items which are on the local tree but not in StarTeam. It is
  753. * assumed that this method will not be called until all the items in
  754. * the corresponding folder have been processed, and that the internal
  755. * map * will contain only uncontrolled items.
  756. */
  757. abstract void processUncontrolledItems() throws BuildException;
  758. /**
  759. * overrides must define this to declare how this method knows if it
  760. * is active. This presents extra clock cycles when the functionality
  761. * is not called for.
  762. *
  763. * @return True if this object is to perform its functionality.
  764. */
  765. protected abstract boolean isActive();
  766. }
  767. }