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
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.nbbuild;
043:
044: import java.io.File;
045: import java.util.ArrayList;
046: import java.util.Hashtable;
047: import java.util.List;
048: import java.util.StringTokenizer;
049: import java.util.Vector;
050:
051: import org.apache.tools.ant.BuildException;
052: import org.apache.tools.ant.Project;
053: import org.apache.tools.ant.Target;
054: import org.apache.tools.ant.Task;
055: import org.apache.tools.ant.taskdefs.Ant;
056:
057: /** Runs a clean task (for example) in all submodules.
058: *
059: * @author Jesse Glick
060: */
061: public class CleanAll extends Task {
062:
063: private List<String> modules = new ArrayList<String>();
064: private List<String> failedmodules = new ArrayList<String>();
065: private String targetname = "clean";
066: private File topdir = null;
067: private File[] topdirs = null;
068: private boolean resolvedependencies = false; // resolve compile-time dependencies for clean
069: private String deptargetprefix = ""; // target prefix for resolving dependencies
070: private Hashtable targets;
071: private boolean failonerror = true; // fail if particular module build failed?
072:
073: /** Comma-separated list of modules to include. */
074: public void setModules(String s) {
075: StringTokenizer tok = new StringTokenizer(s, ", ");
076: modules = new ArrayList<String>();
077: while (tok.hasMoreTokens())
078: modules.add(tok.nextToken());
079: }
080:
081: /** Name of the target to run in each module's build script. */
082: public void setTargetname(String s) {
083: targetname = s;
084: }
085:
086: /** Prefix of compile targets in current build script for
087: * each module.
088: */
089: public void setDepTargetPrefix(String s) {
090: deptargetprefix = s;
091: }
092:
093: /** Enable/Disable resolving compile-time dependencies. */
094: public void setResolveDependencies(boolean b) {
095: resolvedependencies = b;
096: }
097:
098: /** Enable/Disable BUILD FAILED, when particular module's
099: * build failed.
100: */
101: public void setFailOnError(boolean b) {
102: failonerror = b;
103: }
104:
105: /** The top directory containing these modules as subdirectories. */
106: public void setTopdir(File f) {
107: topdir = f;
108: }
109:
110: public void setTopdirs(String str) {
111: StringTokenizer st = new StringTokenizer(str, ",");
112: int count = st.countTokens();
113: topdirs = new File[count];
114: for (int i = 0; i < count; i++) {
115: topdirs[i] = new File(st.nextToken().trim());
116: }
117: }
118:
119: /** Resolve compile-time dependencies and use them for cleaning */
120: private void resolveDependencies() throws BuildException {
121: Target dummy = new Target();
122: String dummyName = "nbmerge-" + getOwningTarget().getName();
123: targets = getProject().getTargets();
124: while (targets.contains(dummyName))
125: dummyName += "-x";
126: dummy.setName(dummyName);
127: for (String module : modules) {
128: dummy.addDependency(deptargetprefix + module);
129: }
130: getProject().addTarget(dummy);
131: @SuppressWarnings("unchecked")
132: Vector<Target> fullList = getProject().topoSort(dummyName,
133: targets);
134: // Now remove earlier ones: already done.
135: @SuppressWarnings("unchecked")
136: Vector<Target> doneList = getProject().topoSort(
137: getOwningTarget().getName(), targets);
138: List<Target> todo = new ArrayList<Target>(fullList.subList(0,
139: fullList.indexOf(dummy)));
140: todo.removeAll(doneList.subList(0, doneList
141: .indexOf(getOwningTarget())));
142:
143: for (Target t : todo) {
144: String _targetname = t.getName();
145: if (_targetname.startsWith(deptargetprefix)) {
146: String module = _targetname.substring(deptargetprefix
147: .length());
148: if (modules.indexOf(module) < 0) {
149: modules.add(module);
150: log("Adding dependency module \"" + module
151: + "\" to the list of modules for cleaning",
152: Project.MSG_VERBOSE);
153: }
154: }
155: }
156: }
157:
158: public void execute() throws BuildException {
159:
160: if (topdirs == null && topdir != null) {
161: topdirs = new File[1];
162: topdirs[0] = topdir;
163: }
164:
165: if (topdir == null && topdirs == null) {
166: throw new BuildException(
167: "You must set at least one topdir attribute",
168: getLocation());
169: }
170:
171: if (resolvedependencies)
172: resolveDependencies();
173:
174: for (int j = 0; j < topdirs.length; j++) {
175: topdir = topdirs[j];
176: for (String module : modules) {
177: Ant ant = (Ant) getProject().createTask("ant");
178: ant.init();
179: ant.setLocation(getLocation());
180: File fl = new File(topdir.getAbsolutePath()
181: + File.separatorChar + module
182: + File.separatorChar + "build.xml");
183: if (!fl.exists()) {
184: continue;
185: }
186: ant.setDir(new File(topdir, module));
187: ant.setTarget(targetname);
188: try {
189: log("Process '" + module + "' location with '"
190: + targetname + "' target", Project.MSG_INFO);
191: ant.execute();
192: } catch (BuildException be) {
193: if (failonerror) {
194: throw new BuildException(be.getMessage(), be,
195: getLocation());
196: } else {
197: log("Target \"" + targetname
198: + "\" failed in module \"" + module
199: + "\"", Project.MSG_WARN);
200: log(fl.getAbsolutePath());
201: log(be.getMessage());
202: String fname = fl.getAbsolutePath();
203: failedmodules.add(fname);
204: }
205: }
206: }
207: }
208: if (failedmodules.size() > 0) {
209: log(
210: "<cleanall> SOME MODULES FAILED TO BUILD, BUT THEIR BuildException WAS CAUGHT",
211: Project.MSG_WARN);
212: log("<cleanall> cleanfailedmodules=\""
213: + failedmodules.toString() + "\"", Project.MSG_WARN);
214: }
215: }
216: }
|