001: package org.tigris.scarab.actions.setup;
002:
003: /* ================================================================
004: * Copyright (c) 2000-2002 CollabNet. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are
008: * met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: import java.io.File;
050: import java.io.PrintStream;
051: import java.util.Hashtable;
052: import java.util.Iterator;
053: import java.util.Map;
054:
055: import org.apache.tools.ant.BuildLogger;
056: import org.apache.tools.ant.DefaultLogger;
057: import org.apache.tools.ant.DemuxOutputStream;
058: import org.apache.tools.ant.Main;
059: import org.apache.tools.ant.Project;
060: import org.apache.tools.ant.ProjectHelper;
061: import org.apache.tools.ant.input.DefaultInputHandler;
062: import org.apache.tools.ant.input.InputHandler;
063:
064: /**
065: * This class is the bridge to ant.
066: * Most of the code is derived form the
067: * org.apache.ant.Main class, but simplyfied for
068: * our purposes. i.e. you can only run one single
069: * ant task per call. Also most of the configuration
070: * properties available in the original class have
071: * been dropped to keep the bridge small.
072: * We could have used the ant Main class directly,
073: * but i think, having control over what happens
074: * here is better (i.e. where does out and err go,
075: * how do we log, etc...)
076: *
077: * @author <a href="mailto:dabbous@saxess.com">Hussayn Dabbous</a>
078: * @version $Id: AntRunner.java 9325 2004-12-22 22:48:10Z dabbous $
079: */
080: public class AntRunner {
081:
082: /**
083: * Cache of the Ant version information when it has been loaded.
084: */
085: private static String antVersion = null;
086:
087: /**
088: * The Ant logger class. There may be only one logger. It will have
089: * the right to use the 'out' PrintStream. The class must implements the
090: * BuildLogger interface.
091: */
092: private String loggerClassname = null;
093:
094: /** Our current message output status. Follows Project.MSG_XXX. */
095: private int msgOutputLevel = Project.MSG_INFO;
096:
097: /** Stream to use for logging. */
098: private static PrintStream out = System.out;
099:
100: /** Stream that we are using for logging error messages. */
101: private static PrintStream err = System.err;
102:
103: /**
104: * Execute the given target in the given buildFile.
105: * If target is null, the default target is executred.
106: * theBuildfile must NOT be null. and readable in the
107: * current sessoin context.
108: * Currently no exception handling. Every Exception is
109: * rethrown.
110: * @param theBuildFile
111: * @param theTarget
112: */
113: public void execute(File theBuildFile, String theTarget,
114: Map properties) {
115:
116: final Project project = new Project();
117: project.setCoreLoader(null);
118:
119: Throwable error = null;
120:
121: try {
122: addBuildListener(project);
123: addInputHandler(project);
124:
125: PrintStream err = System.err;
126: PrintStream out = System.out;
127:
128: // use a system manager that prevents from System.exit()
129: SecurityManager oldsm = System.getSecurityManager();
130:
131: try {
132: System.setOut(new PrintStream(new DemuxOutputStream(
133: project, false)));
134: System.setErr(new PrintStream(new DemuxOutputStream(
135: project, true)));
136: project.fireBuildStarted();
137:
138: project.init();
139: project.setUserProperty("ant.version", Main
140: .getAntVersion());
141: project.setUserProperty("ant.file", theBuildFile
142: .getAbsolutePath());
143:
144: if (properties != null) {
145: Iterator iter = properties.keySet().iterator();
146: while (iter.hasNext()) {
147: String key = (String) iter.next();
148: String val = (String) properties.get(key);
149: project.setUserProperty(key, val);
150: }
151: }
152:
153: ProjectHelper.configureProject(project, theBuildFile);
154:
155: if (theTarget == null) {
156: theTarget = project.getDefaultTarget();
157: }
158:
159: project.executeTarget(theTarget);
160:
161: } finally {
162: // put back the original security manager
163: // actually, did it ever change ???
164: // Need to look into the ant sources to answer this
165: // question [HD]
166: if (oldsm != null) {
167: System.setSecurityManager(oldsm);
168: }
169:
170: System.setOut(out);
171: System.setErr(err);
172: }
173: } catch (RuntimeException exc) {
174: error = exc;
175: throw exc;
176: } catch (Error err) {
177: error = err;
178: throw err;
179: } finally {
180: project.fireBuildFinished(error);
181: }
182:
183: }
184:
185: protected void addBuildListener(Project project) {
186: // Add the default listener
187: BuildLogger logger = createLogger();
188: project.addBuildListener(logger);
189: }
190:
191: private void addInputHandler(Project project) {
192: InputHandler handler = new DefaultInputHandler();
193: project.setInputHandler(handler);
194: }
195:
196: private BuildLogger createLogger() {
197: BuildLogger logger = null;
198: if (loggerClassname != null) {
199: try {
200: logger = (BuildLogger) (Class.forName(loggerClassname)
201: .newInstance());
202: } catch (ClassCastException e) {
203: System.err
204: .println("The specified logger class "
205: + loggerClassname
206: + " does not implement the BuildLogger interface");
207: throw new RuntimeException();
208: } catch (Exception e) {
209: System.err
210: .println("Unable to instantiate specified logger "
211: + "class "
212: + loggerClassname
213: + " : "
214: + e.getClass().getName());
215: throw new RuntimeException();
216: }
217: } else {
218: logger = new DefaultLogger();
219: }
220:
221: logger.setMessageOutputLevel(msgOutputLevel);
222: logger.setOutputPrintStream(out);
223: logger.setErrorPrintStream(err);
224: logger.setEmacsMode(false);
225:
226: return logger;
227: }
228:
229: static public void main(String[] args) {
230: String theBuildFileName = args[0];
231: File theBuildFile = new File(theBuildFileName);
232: String theTarget = args[1];
233: Map properties = null;
234: for (int index = 2; index < args.length; index++) {
235: if (properties == null) {
236: properties = new Hashtable();
237: }
238: String pdef = args[index];
239: int i = pdef.indexOf('=');
240: String key;
241: String val;
242: if (i > 0) {
243: key = pdef.substring(0, i);
244: val = pdef.substring(i + 1);
245: } else {
246: key = pdef;
247: val = "";
248: }
249: properties.put(key, val);
250: }
251:
252: AntRunner antRunner = new AntRunner();
253: antRunner.execute(theBuildFile, theTarget, properties);
254:
255: }
256:
257: }
|