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. /*
  18. * Portions of this software are based upon public domain software
  19. * originally written at the National Center for Supercomputing Applications,
  20. * University of Illinois, Urbana-Champaign.
  21. */
  22. package org.apache.tools.ant.taskdefs.optional.perforce;
  23. import java.io.IOException;
  24. import org.apache.oro.text.perl.Perl5Util;
  25. import org.apache.tools.ant.BuildException;
  26. import org.apache.tools.ant.Project;
  27. import org.apache.tools.ant.taskdefs.Execute;
  28. import org.apache.tools.ant.types.Commandline;
  29. /** Base class for Perforce (P4) ANT tasks. See individual task for example usage.
  30. *
  31. * @see P4Sync
  32. * @see P4Have
  33. * @see P4Change
  34. * @see P4Edit
  35. * @see P4Submit
  36. * @see P4Label
  37. * @see org.apache.tools.ant.taskdefs.Execute
  38. */
  39. public abstract class P4Base extends org.apache.tools.ant.Task {
  40. /**Perl5 regexp in Java - cool eh? */
  41. protected Perl5Util util = null;
  42. /** The OS shell to use (cmd.exe or /bin/sh) */
  43. protected String shell;
  44. //P4 runtime directives
  45. /** Perforce Server Port (eg KM01:1666) */
  46. protected String P4Port = "";
  47. /** Perforce Client (eg myclientspec) */
  48. protected String P4Client = "";
  49. /** Perforce User (eg fbloggs) */
  50. protected String P4User = "";
  51. /** Perforce view for commands. (eg //projects/foobar/main/source/... )*/
  52. protected String P4View = "";
  53. // Perforce task directives
  54. /** Keep going or fail on error - defaults to fail. */
  55. protected boolean failOnError = true;
  56. //P4 g-opts and cmd opts (rtfm)
  57. /** Perforce 'global' opts.
  58. * Forms half of low level API */
  59. protected String P4Opts = "";
  60. /** Perforce command opts.
  61. * Forms half of low level API */
  62. protected String P4CmdOpts = "";
  63. /** Set by the task or a handler to indicate that the task has failed. BuildExceptions
  64. * can also be thrown to indicate failure. */
  65. private boolean inError = false;
  66. /** If inError is set, then errorMessage needs to contain the reason why. */
  67. private String errorMessage = "";
  68. /**
  69. * gets whether or not the task has encountered an error
  70. * @return error flag
  71. * @since ant 1.6
  72. */
  73. public boolean getInError() {
  74. return inError;
  75. }
  76. /**
  77. * sets the error flag on the task
  78. * @param inError if true an error has been encountered by the handler
  79. * @since ant 1.6
  80. */
  81. public void setInError(boolean inError) {
  82. this.inError = inError;
  83. }
  84. /**
  85. * gets the error message recorded by the Perforce handler
  86. * @return error message
  87. */
  88. public String getErrorMessage() {
  89. return errorMessage;
  90. }
  91. /**
  92. * sets the error message
  93. * @param errorMessage line of error output
  94. */
  95. public void setErrorMessage(String errorMessage) {
  96. this.errorMessage = errorMessage;
  97. }
  98. //Setters called by Ant
  99. /**
  100. * The p4d server and port to connect to;
  101. * optional, default "perforce:1666"
  102. *
  103. * @param P4Port the port one wants to set such as localhost:1666
  104. */
  105. public void setPort(String P4Port) {
  106. this.P4Port = "-p" + P4Port;
  107. }
  108. /**
  109. * The p4 client spec to use;
  110. * optional, defaults to the current user
  111. *
  112. * @param P4Client the name of the Perforce client spec
  113. */
  114. public void setClient(String P4Client) {
  115. this.P4Client = "-c" + P4Client;
  116. }
  117. /**
  118. * The p4 username;
  119. * optional, defaults to the current user
  120. *
  121. * @param P4User the user name
  122. */
  123. public void setUser(String P4User) {
  124. this.P4User = "-u" + P4User;
  125. }
  126. /**
  127. * Set global P4 options; Used on all
  128. * of the Perforce tasks.
  129. *
  130. * @param P4Opts global options, to use a specific P4Config file for instance
  131. */
  132. public void setGlobalopts(String P4Opts) {
  133. this.P4Opts = P4Opts;
  134. }
  135. /**
  136. * The client, branch or label view to operate upon;
  137. * optional default "//...".
  138. *
  139. * the view is required for the following tasks :
  140. * <ul>
  141. * <li>p4delete</li>
  142. * <li>p4edit</li>
  143. * <li>p4reopen</li>
  144. * <li>p4resolve</li>
  145. * </ul>
  146. *
  147. * @param P4View the view one wants to use
  148. */
  149. public void setView(String P4View) {
  150. this.P4View = P4View;
  151. }
  152. /**
  153. * Set extra command options; only used on some
  154. * of the Perforce tasks.
  155. *
  156. * @param P4CmdOpts command line options going after the particular
  157. * Perforce command
  158. */
  159. public void setCmdopts(String P4CmdOpts) {
  160. this.P4CmdOpts = P4CmdOpts;
  161. }
  162. /**
  163. * whether to stop the build (true, default)
  164. * or keep going if an error is returned from the p4 command
  165. * @param fail indicates whether one wants to fail the build if an error comes from the
  166. * Perforce command
  167. */
  168. public void setFailonerror(boolean fail) {
  169. failOnError = fail;
  170. }
  171. /**
  172. * sets attributes Port, Client, User from properties
  173. * if these properties are defined.
  174. * Called automatically by UnknownElement
  175. * @see org.apache.tools.ant.UnknownElement
  176. * <table>
  177. * <tr><th>Property</th><th>Attribute</th></tr>
  178. * <tr><td>p4.port</td><td>Port</td></tr>
  179. * <tr><td>p4.client</td><td>Client</td></tr>
  180. * <tr><td>p4.user</td><td>User</td></tr>
  181. * </table>
  182. */
  183. public void init() {
  184. util = new Perl5Util();
  185. //Get default P4 settings from environment - Mark would have done something cool with
  186. //introspection here.....:-)
  187. String tmpprop;
  188. if ((tmpprop = getProject().getProperty("p4.port")) != null) {
  189. setPort(tmpprop);
  190. }
  191. if ((tmpprop = getProject().getProperty("p4.client")) != null) {
  192. setClient(tmpprop);
  193. }
  194. if ((tmpprop = getProject().getProperty("p4.user")) != null) {
  195. setUser(tmpprop);
  196. }
  197. }
  198. /**
  199. * no usages found for this method
  200. * runs a Perforce command without a handler
  201. * @param command the command that one wants to execute
  202. * @throws BuildException if failonerror is set and the command fails
  203. */
  204. protected void execP4Command(String command) throws BuildException {
  205. execP4Command(command, null);
  206. }
  207. /**
  208. * Execute P4 command assembled by subclasses.
  209. *
  210. * @param command The command to run
  211. * @param handler A P4Handler to process any input and output
  212. *
  213. * @throws BuildException if failonerror has been set to true
  214. */
  215. protected void execP4Command(String command, P4Handler handler) throws BuildException {
  216. try {
  217. // reset error flags before executing the command
  218. inError = false;
  219. errorMessage = "";
  220. Commandline commandline = new Commandline();
  221. commandline.setExecutable("p4");
  222. //Check API for these - it's how CVS does it...
  223. if (P4Port != null && P4Port.length() != 0) {
  224. commandline.createArgument().setValue(P4Port);
  225. }
  226. if (P4User != null && P4User.length() != 0) {
  227. commandline.createArgument().setValue(P4User);
  228. }
  229. if (P4Client != null && P4Client.length() != 0) {
  230. commandline.createArgument().setValue(P4Client);
  231. }
  232. if (P4Opts != null && P4Opts.length() != 0) {
  233. commandline.createArgument().setLine(P4Opts);
  234. }
  235. commandline.createArgument().setLine(command);
  236. log(commandline.describeCommand(), Project.MSG_VERBOSE);
  237. if (handler == null) {
  238. handler = new SimpleP4OutputHandler(this);
  239. }
  240. Execute exe = new Execute(handler, null);
  241. exe.setAntRun(getProject());
  242. exe.setCommandline(commandline.getCommandline());
  243. try {
  244. exe.execute();
  245. if (inError && failOnError) {
  246. throw new BuildException(errorMessage);
  247. }
  248. } catch (IOException e) {
  249. throw new BuildException(e);
  250. } finally {
  251. try {
  252. handler.stop();
  253. } catch (Exception e) {
  254. log(e.toString(), Project.MSG_ERR);
  255. }
  256. }
  257. } catch (Exception e) {
  258. String failMsg = "Problem exec'ing P4 command: " + e.getMessage();
  259. if (failOnError) {
  260. throw new BuildException(failMsg);
  261. } else {
  262. log(failMsg, Project.MSG_ERR);
  263. }
  264. }
  265. }
  266. }