/* * 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 the setAction() 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; } }