/* * Copyright 2001-2002,2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.tools.ant.taskdefs; import java.util.Hashtable; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.EnumeratedAttribute; /** * Adds a listener to the current build process that records the * output to a file. *
Several recorders can exist at the same time. Each recorder is * associated with a file. The filename is used as a unique identifier for * the recorders. The first call to the recorder task with an unused filename * will create a recorder (using the parameters provided) and add it to the * listeners of the build. All subsequent calls to the recorder task using * this filename will modify that recorders state (recording or not) or other * properties (like logging level).
*Some technical issues: the file's print stream is flushed for "finished" * events (buildFinished, targetFinished and taskFinished), and is closed on * a buildFinished event.
* @see RecorderEntry * @version 0.5 * @since Ant 1.4 * @ant.task name="record" category="utility" */ public class Recorder extends Task { ////////////////////////////////////////////////////////////////////// // ATTRIBUTES /** The name of the file to record to. */ private String filename = null; /** * Whether or not to append. Need Boolean to record an unset state (null). */ private Boolean append = null; /** * Whether to start or stop recording. Need Boolean to record an unset * state (null). */ private Boolean start = null; /** The level to log at. A level of -1 means not initialized yet. */ private int loglevel = -1; /** Strip task banners if true. */ private boolean emacsMode = false; /** The list of recorder entries. */ private static Hashtable recorderEntries = new Hashtable(); ////////////////////////////////////////////////////////////////////// // CONSTRUCTORS / INITIALIZERS ////////////////////////////////////////////////////////////////////// // ACCESSOR METHODS /** * Sets the name of the file to log to, and the name of the recorder * entry. * * @param fname File name of logfile. */ public void setName(String fname) { filename = fname; } /** * Sets the action for the associated recorder entry. * * @param action The action for the entry to take: start or stop. */ public void setAction(ActionChoices action) { if (action.getValue().equalsIgnoreCase("start")) { start = Boolean.TRUE; } else { start = Boolean.FALSE; } } /** * Whether or not the logger should append to a previous file. * @param append if true, append to a previous file. */ public void setAppend(boolean append) { this.append = (append ? Boolean.TRUE : Boolean.FALSE); } /** * Set emacs mode. * @param emacsMode if true use emacs mode */ public void setEmacsMode(boolean emacsMode) { this.emacsMode = emacsMode; } /** * Sets the level to which this recorder entry should log to. * * @see VerbosityLevelChoices */ public void setLoglevel(VerbosityLevelChoices level) { //I hate cascading if/elseif clauses !!! String lev = level.getValue(); if (lev.equalsIgnoreCase("error")) { loglevel = Project.MSG_ERR; } else if (lev.equalsIgnoreCase("warn")) { loglevel = Project.MSG_WARN; } else if (lev.equalsIgnoreCase("info")) { loglevel = Project.MSG_INFO; } else if (lev.equalsIgnoreCase("verbose")) { loglevel = Project.MSG_VERBOSE; } else if (lev.equalsIgnoreCase("debug")) { loglevel = Project.MSG_DEBUG; } } ////////////////////////////////////////////////////////////////////// // CORE / MAIN BODY /** * The main execution. * @throws BuildException on error */ public void execute() throws BuildException { if (filename == null) { throw new BuildException("No filename specified"); } getProject().log("setting a recorder for name " + filename, Project.MSG_DEBUG); // get the recorder entry RecorderEntry recorder = getRecorder(filename, getProject()); // set the values on the recorder recorder.setMessageOutputLevel(loglevel); if (start != null) { if (start.booleanValue()) { recorder.reopenFile(); recorder.setRecordState(start); } else { recorder.setRecordState(start); recorder.closeFile(); } } recorder.setEmacsMode(emacsMode); } ////////////////////////////////////////////////////////////////////// // INNER CLASSES /** * A list of possible values for thesetAction()
method.
* Possible values include: start and stop.
*/
public static class ActionChoices extends EnumeratedAttribute {
private static final String[] VALUES = {"start", "stop"};
/**
* @see EnumeratedAttribute#getValues()
*/
public String[] getValues() {
return VALUES;
}
}
/**
* A list of possible values for the setLoglevel()
method.
* Possible values include: error, warn, info, verbose, debug.
*/
public static class VerbosityLevelChoices extends EnumeratedAttribute {
private static final String[] VALUES = {"error", "warn", "info",
"verbose", "debug"};
/**
* @see EnumeratedAttribute#getValues()
*/
public String[] getValues() {
return VALUES;
}
}
/**
* Gets the recorder that's associated with the passed in name. If the
* recorder doesn't exist, then a new one is created.
* @param name the name of the recoder
* @param proj the current project
* @return a recorder
* @throws BuildException on error
*/
protected RecorderEntry getRecorder(String name, Project proj)
throws BuildException {
Object o = recorderEntries.get(name);
RecorderEntry entry;
if (o == null) {
// create a recorder entry
entry = new RecorderEntry(name);
if (append == null) {
entry.openFile(false);
} else {
entry.openFile(append.booleanValue());
}
entry.setProject(proj);
recorderEntries.put(name, entry);
} else {
entry = (RecorderEntry) o;
}
return entry;
}
}