001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.infra.build.ant;
038:
039: import java.util.LinkedList;
040: import java.util.List;
041: import org.apache.tools.ant.BuildException;
042: import org.apache.tools.ant.Task;
043: import org.apache.tools.ant.TaskContainer;
044:
045: /**
046: * This class is an ant task which adds the for-loop functionality. It is an
047: * arbitrary tasks container, which is capable of executing its childrne ina loop.
048: *
049: * <p>
050: * Two types of loops are supported. First, iterating of over a list of values; in
051: * this case the <code>list</code> and <code>separator</code> (optional) attributes
052: * should be set and the property speficied with <code>property</code> attribute
053: * will be set to each of the value speficied in the the list.
054: *
055: * <p>
056: * Second, iterating of a range of integers. In this case the <code>from</code>,
057: * <code>to</code> and <code>increment</code> (optional) attributes should be set,
058: * meaning the starting point, the finish point and the step. Note that if one
059: * specifies a negative step, the iteration could go backwards.
060: *
061: * <p>
062: * If a mixture of attributes is supplied, iterating over a list is preferred.
063: *
064: * @author Kirill Sorokin
065: */
066: public class ForEach extends Task implements TaskContainer {
067: /////////////////////////////////////////////////////////////////////////////////
068: // Instance
069: /**
070: * The list of values over which the iteration process should go.
071: */
072: private String list;
073:
074: /**
075: * Separator token which should be used to split the list string into individual
076: * values.
077: */
078: private String separator;
079:
080: /**
081: * Starting point for iteration over an integer range.
082: */
083: private int from;
084:
085: /**
086: * Ending point for iteration over an integer range.
087: */
088: private int to;
089:
090: /**
091: * Step amount for iteration over an integer range.
092: */
093: private int increment;
094:
095: /**
096: * Name of the property which has to be set for each iteration.
097: */
098: private String property;
099:
100: /**
101: * List of child tasks which should be executed at each iteration.
102: */
103: private List<Task> children;
104:
105: /**
106: * Flag which marks incorrect attribute values.
107: */
108: private boolean wrongArgs;
109:
110: // constructor //////////////////////////////////////////////////////////////////
111: /**
112: * Constructs a new instance of the {@link ForEach} task. It simply sets the
113: * default values for the attributes.
114: */
115: public ForEach() {
116: separator = DEFAULT_SEPARATOR;
117:
118: from = DEFAULT_FROM;
119: to = DEFAULT_TO;
120: increment = DEFAULT_INCREMENT;
121:
122: children = new LinkedList<Task>();
123: }
124:
125: // setters //////////////////////////////////////////////////////////////////////
126: /**
127: * Setter for the 'list' property.
128: *
129: * @param list The new value for the 'list' property.
130: */
131: public void setList(final String list) {
132: this .list = list;
133: }
134:
135: /**
136: * Setter for the 'separator' property.
137: *
138: * @param separator The new value for the 'separator' property.
139: */
140: public void setSeparator(final String separator) {
141: this .separator = separator;
142: }
143:
144: /**
145: * Setter for the 'property' property.
146: *
147: * @param property The new value for the 'property' property.
148: */
149: public void setProperty(final String property) {
150: this .property = property;
151: }
152:
153: /**
154: * Setter for the 'from' property.
155: *
156: * @param from The new value for the 'from' property.
157: */
158: public void setFrom(final String from) {
159: try {
160: this .from = Integer.parseInt(from);
161: } catch (NumberFormatException e) {
162: log("Wrong value for parameter 'from'."); // NOI18N
163: wrongArgs = true;
164: }
165: }
166:
167: /**
168: * Setter for the 'to' property.
169: *
170: * @param to The new value for the 'to' property.
171: */
172: public void setTo(final String to) {
173: try {
174: this .to = Integer.parseInt(to);
175: } catch (NumberFormatException e) {
176: log("Wrong value for parameter 'to'."); // NOI18N
177: wrongArgs = true;
178: }
179: }
180:
181: /**
182: * Setter for the 'increment' property.
183: *
184: * @param increment The new value for the 'increment' property.
185: */
186: public void setIncrement(final String increment) {
187: try {
188: this .increment = Integer.parseInt(increment);
189: } catch (NumberFormatException e) {
190: log("Wrong value for parameter 'increment'."); // NOI18N
191: wrongArgs = true;
192: }
193: }
194:
195: /**
196: * Registers a child task. The supplied <code>Task</code> object will be added
197: * to the list of child tasks and then executed at each iteration.
198: *
199: * @param task The <code>Task</code> object to register.
200: */
201: public void addTask(final Task task) {
202: children.add(task);
203: }
204:
205: // execution ////////////////////////////////////////////////////////////////////
206: /**
207: * Executes the task. Basing on which attributes were set, the choice is made of
208: * whether the iteration should happen over a list or an integer range. Then the
209: * iteration takes place the specified property is set and the child tasks are
210: * executed.
211: *
212: * @throws org.apache.tools.ant.BuildException if a child task fails to execute.
213: */
214: public void execute() throws BuildException {
215: if (wrongArgs) {
216: throw new BuildException(
217: "Correct parameters were not supplied."); // NOI18N
218: }
219:
220: if (list != null) {
221: final String[] items = list.split(separator);
222:
223: for (String value : items) {
224: executeChildren(value);
225: }
226: return;
227: } else {
228: for (int i = from; i <= to; i += increment) {
229: executeChildren(Integer.toString(i));
230: }
231: }
232: }
233:
234: // private //////////////////////////////////////////////////////////////////////
235: /**
236: * Sets the specified property to the given value and executes the children.
237: */
238: private void executeChildren(String value) throws BuildException {
239: getProject().setProperty(this .property, value);
240:
241: for (Task task : this .children) {
242: task.perform();
243: }
244: }
245:
246: /////////////////////////////////////////////////////////////////////////////////
247: // Constants
248: /**
249: * Default value for the 'separator' property.
250: */
251: private static final String DEFAULT_SEPARATOR = " "; // NOI18N
252:
253: /**
254: * Default value for the 'from' property.
255: */
256: private static final int DEFAULT_FROM = 0; // NOMAGI
257:
258: /**
259: * Default value for the 'to' property.
260: */
261: private static final int DEFAULT_TO = 0; // NOMAGI
262:
263: /**
264: * Default value for the 'increment' property.
265: */
266: private static final int DEFAULT_INCREMENT = 1; // NOMAGI
267: }
|