001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: /*
019: * Portions of this software are based upon public domain software
020: * originally written at the National Center for Supercomputing Applications,
021: * University of Illinois, Urbana-Champaign.
022: */
023:
024: package org.apache.tools.ant.taskdefs.optional.perforce;
025:
026: import java.io.IOException;
027: import org.apache.oro.text.perl.Perl5Util;
028: import org.apache.tools.ant.BuildException;
029: import org.apache.tools.ant.Project;
030: import org.apache.tools.ant.taskdefs.Execute;
031: import org.apache.tools.ant.types.Commandline;
032:
033: /** Base class for Perforce (P4) ANT tasks. See individual task for example usage.
034: *
035: * @see P4Sync
036: * @see P4Have
037: * @see P4Change
038: * @see P4Edit
039: * @see P4Submit
040: * @see P4Label
041: * @see org.apache.tools.ant.taskdefs.Execute
042: */
043: public abstract class P4Base extends org.apache.tools.ant.Task {
044: // CheckStyle:VisibilityModifier OFF - bc
045: // CheckStyle:MemberNameCheck OFF - bc
046: /**Perl5 regexp in Java - cool eh? */
047: protected Perl5Util util = null;
048: /** The OS shell to use (cmd.exe or /bin/sh) */
049: protected String shell;
050:
051: //P4 runtime directives
052: /** Perforce Server Port (eg KM01:1666) */
053: protected String P4Port = "";
054: /** Perforce Client (eg myclientspec) */
055: protected String P4Client = "";
056: /** Perforce User (eg fbloggs) */
057: protected String P4User = "";
058: /** Perforce view for commands. (eg //projects/foobar/main/source/... )*/
059: protected String P4View = "";
060:
061: // Perforce task directives
062: /** Keep going or fail on error - defaults to fail. */
063: protected boolean failOnError = true;
064:
065: //P4 g-opts and cmd opts (rtfm)
066: /** Perforce 'global' opts.
067: * Forms half of low level API */
068: protected String P4Opts = "";
069: /** Perforce command opts.
070: * Forms half of low level API */
071: protected String P4CmdOpts = "";
072:
073: /** Set by the task or a handler to indicate that the task has failed. BuildExceptions
074: * can also be thrown to indicate failure. */
075: private boolean inError = false;
076:
077: /** If inError is set, then errorMessage needs to contain the reason why. */
078: private String errorMessage = "";
079:
080: // CheckStyle:MemberNameCheck ON
081: // CheckStyle:VisibilityModifier ON
082:
083: /**
084: * gets whether or not the task has encountered an error
085: * @return error flag
086: * @since ant 1.6
087: */
088: public boolean getInError() {
089: return inError;
090: }
091:
092: /**
093: * sets the error flag on the task
094: * @param inError if true an error has been encountered by the handler
095: * @since ant 1.6
096: */
097: public void setInError(boolean inError) {
098: this .inError = inError;
099: }
100:
101: /**
102: * gets the error message recorded by the Perforce handler
103: * @return error message
104: */
105: public String getErrorMessage() {
106: return errorMessage;
107: }
108:
109: /**
110: * sets the error message
111: * @param errorMessage line of error output
112: */
113: public void setErrorMessage(String errorMessage) {
114: this .errorMessage = errorMessage;
115: }
116:
117: //Setters called by Ant
118:
119: /**
120: * The p4d server and port to connect to;
121: * optional, default "perforce:1666"
122: *
123: * @param p4Port the port one wants to set such as localhost:1666
124: */
125: public void setPort(String p4Port) {
126: this .P4Port = "-p" + p4Port;
127: }
128:
129: /**
130: * The p4 client spec to use;
131: * optional, defaults to the current user
132: *
133: * @param p4Client the name of the Perforce client spec
134: */
135: public void setClient(String p4Client) {
136: this .P4Client = "-c" + p4Client;
137: }
138:
139: /**
140: * The p4 username;
141: * optional, defaults to the current user
142: *
143: * @param p4User the user name
144: */
145: public void setUser(String p4User) {
146: this .P4User = "-u" + p4User;
147: }
148:
149: /**
150: * Set global P4 options; Used on all
151: * of the Perforce tasks.
152: *
153: * @param p4Opts global options, to use a specific P4Config file for instance
154: */
155: public void setGlobalopts(String p4Opts) {
156: this .P4Opts = p4Opts;
157: }
158:
159: /**
160: * The client, branch or label view to operate upon;
161: * optional default "//...".
162: *
163: * the view is required for the following tasks :
164: * <ul>
165: * <li>p4delete</li>
166: * <li>p4edit</li>
167: * <li>p4reopen</li>
168: * <li>p4resolve</li>
169: * </ul>
170: *
171: * @param p4View the view one wants to use
172: */
173: public void setView(String p4View) {
174: this .P4View = p4View;
175: }
176:
177: /**
178: * Set extra command options; only used on some
179: * of the Perforce tasks.
180: *
181: * @param p4CmdOpts command line options going after the particular
182: * Perforce command
183: */
184: public void setCmdopts(String p4CmdOpts) {
185: this .P4CmdOpts = p4CmdOpts;
186: }
187:
188: /**
189: * whether to stop the build (true, default)
190: * or keep going if an error is returned from the p4 command
191: * @param fail indicates whether one wants to fail the build if an error comes from the
192: * Perforce command
193: */
194: public void setFailonerror(boolean fail) {
195: failOnError = fail;
196: }
197:
198: /**
199: * sets attributes Port, Client, User from properties
200: * if these properties are defined.
201: * Called automatically by UnknownElement
202: * @see org.apache.tools.ant.UnknownElement
203: * <table>
204: * <tr><th>Property</th><th>Attribute</th></tr>
205: * <tr><td>p4.port</td><td>Port</td></tr>
206: * <tr><td>p4.client</td><td>Client</td></tr>
207: * <tr><td>p4.user</td><td>User</td></tr>
208: * </table>
209: */
210: public void init() {
211:
212: util = new Perl5Util();
213:
214: //Get default P4 settings from environment - Mark would have done something cool with
215: //introspection here.....:-)
216: String tmpprop;
217: if ((tmpprop = getProject().getProperty("p4.port")) != null) {
218: setPort(tmpprop);
219: }
220: if ((tmpprop = getProject().getProperty("p4.client")) != null) {
221: setClient(tmpprop);
222: }
223: if ((tmpprop = getProject().getProperty("p4.user")) != null) {
224: setUser(tmpprop);
225: }
226: }
227:
228: /**
229: * no usages found for this method
230: * runs a Perforce command without a handler
231: * @param command the command that one wants to execute
232: * @throws BuildException if failonerror is set and the command fails
233: */
234: protected void execP4Command(String command) throws BuildException {
235: execP4Command(command, null);
236: }
237:
238: /**
239: * Execute P4 command assembled by subclasses.
240: *
241: * @param command The command to run
242: * @param handler A P4Handler to process any input and output
243: *
244: * @throws BuildException if failonerror has been set to true
245: */
246: protected void execP4Command(String command, P4Handler handler)
247: throws BuildException {
248: try {
249: // reset error flags before executing the command
250: inError = false;
251: errorMessage = "";
252: Commandline commandline = new Commandline();
253: commandline.setExecutable("p4");
254:
255: //Check API for these - it's how CVS does it...
256: if (P4Port != null && P4Port.length() != 0) {
257: commandline.createArgument().setValue(P4Port);
258: }
259: if (P4User != null && P4User.length() != 0) {
260: commandline.createArgument().setValue(P4User);
261: }
262: if (P4Client != null && P4Client.length() != 0) {
263: commandline.createArgument().setValue(P4Client);
264: }
265: if (P4Opts != null && P4Opts.length() != 0) {
266: commandline.createArgument().setLine(P4Opts);
267: }
268: commandline.createArgument().setLine(command);
269:
270: log(commandline.describeCommand(), Project.MSG_VERBOSE);
271:
272: if (handler == null) {
273: handler = new SimpleP4OutputHandler(this );
274: }
275:
276: Execute exe = new Execute(handler, null);
277:
278: exe.setAntRun(getProject());
279:
280: exe.setCommandline(commandline.getCommandline());
281:
282: try {
283: exe.execute();
284:
285: if (inError && failOnError) {
286: throw new BuildException(errorMessage);
287: }
288: } catch (IOException e) {
289: throw new BuildException(e);
290: } finally {
291: try {
292: handler.stop();
293: } catch (Exception e) {
294: log(e.toString(), Project.MSG_ERR);
295: }
296: }
297:
298: } catch (Exception e) {
299: String failMsg = "Problem exec'ing P4 command: "
300: + e.getMessage();
301: if (failOnError) {
302: throw new BuildException(failMsg);
303: } else {
304: log(failMsg, Project.MSG_ERR);
305: }
306:
307: }
308: }
309: }
|