1 | /*
|
---|
2 | * Copyright 2001-2002,2004-2005 The Apache Software Foundation
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | *
|
---|
8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
9 | *
|
---|
10 | * Unless required by applicable law or agreed to in writing, software
|
---|
11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
13 | * See the License for the specific language governing permissions and
|
---|
14 | * limitations under the License.
|
---|
15 | *
|
---|
16 | */
|
---|
17 | package org.apache.tools.ant.taskdefs;
|
---|
18 |
|
---|
19 | import java.util.Hashtable;
|
---|
20 | import org.apache.tools.ant.BuildException;
|
---|
21 | import org.apache.tools.ant.Project;
|
---|
22 | import org.apache.tools.ant.Task;
|
---|
23 | import org.apache.tools.ant.types.EnumeratedAttribute;
|
---|
24 |
|
---|
25 | /**
|
---|
26 | * Adds a listener to the current build process that records the
|
---|
27 | * output to a file.
|
---|
28 | * <p>Several recorders can exist at the same time. Each recorder is
|
---|
29 | * associated with a file. The filename is used as a unique identifier for
|
---|
30 | * the recorders. The first call to the recorder task with an unused filename
|
---|
31 | * will create a recorder (using the parameters provided) and add it to the
|
---|
32 | * listeners of the build. All subsequent calls to the recorder task using
|
---|
33 | * this filename will modify that recorders state (recording or not) or other
|
---|
34 | * properties (like logging level).</p>
|
---|
35 | * <p>Some technical issues: the file's print stream is flushed for "finished"
|
---|
36 | * events (buildFinished, targetFinished and taskFinished), and is closed on
|
---|
37 | * a buildFinished event.</p>
|
---|
38 | * @see RecorderEntry
|
---|
39 | * @version 0.5
|
---|
40 | * @since Ant 1.4
|
---|
41 | * @ant.task name="record" category="utility"
|
---|
42 | */
|
---|
43 | public class Recorder extends Task {
|
---|
44 |
|
---|
45 | //////////////////////////////////////////////////////////////////////
|
---|
46 | // ATTRIBUTES
|
---|
47 |
|
---|
48 | /** The name of the file to record to. */
|
---|
49 | private String filename = null;
|
---|
50 | /**
|
---|
51 | * Whether or not to append. Need Boolean to record an unset state (null).
|
---|
52 | */
|
---|
53 | private Boolean append = null;
|
---|
54 | /**
|
---|
55 | * Whether to start or stop recording. Need Boolean to record an unset
|
---|
56 | * state (null).
|
---|
57 | */
|
---|
58 | private Boolean start = null;
|
---|
59 | /** The level to log at. A level of -1 means not initialized yet. */
|
---|
60 | private int loglevel = -1;
|
---|
61 | /** Strip task banners if true. */
|
---|
62 | private boolean emacsMode = false;
|
---|
63 | /** The list of recorder entries. */
|
---|
64 | private static Hashtable recorderEntries = new Hashtable();
|
---|
65 |
|
---|
66 | //////////////////////////////////////////////////////////////////////
|
---|
67 | // CONSTRUCTORS / INITIALIZERS
|
---|
68 |
|
---|
69 | //////////////////////////////////////////////////////////////////////
|
---|
70 | // ACCESSOR METHODS
|
---|
71 |
|
---|
72 | /**
|
---|
73 | * Sets the name of the file to log to, and the name of the recorder
|
---|
74 | * entry.
|
---|
75 | *
|
---|
76 | * @param fname File name of logfile.
|
---|
77 | */
|
---|
78 | public void setName(String fname) {
|
---|
79 | filename = fname;
|
---|
80 | }
|
---|
81 |
|
---|
82 |
|
---|
83 | /**
|
---|
84 | * Sets the action for the associated recorder entry.
|
---|
85 | *
|
---|
86 | * @param action The action for the entry to take: start or stop.
|
---|
87 | */
|
---|
88 | public void setAction(ActionChoices action) {
|
---|
89 | if (action.getValue().equalsIgnoreCase("start")) {
|
---|
90 | start = Boolean.TRUE;
|
---|
91 | } else {
|
---|
92 | start = Boolean.FALSE;
|
---|
93 | }
|
---|
94 | }
|
---|
95 |
|
---|
96 |
|
---|
97 | /**
|
---|
98 | * Whether or not the logger should append to a previous file.
|
---|
99 | * @param append if true, append to a previous file.
|
---|
100 | */
|
---|
101 | public void setAppend(boolean append) {
|
---|
102 | this.append = (append ? Boolean.TRUE : Boolean.FALSE);
|
---|
103 | }
|
---|
104 |
|
---|
105 |
|
---|
106 | /**
|
---|
107 | * Set emacs mode.
|
---|
108 | * @param emacsMode if true use emacs mode
|
---|
109 | */
|
---|
110 | public void setEmacsMode(boolean emacsMode) {
|
---|
111 | this.emacsMode = emacsMode;
|
---|
112 | }
|
---|
113 |
|
---|
114 |
|
---|
115 | /**
|
---|
116 | * Sets the level to which this recorder entry should log to.
|
---|
117 | *
|
---|
118 | * @see VerbosityLevelChoices
|
---|
119 | */
|
---|
120 | public void setLoglevel(VerbosityLevelChoices level) {
|
---|
121 | //I hate cascading if/elseif clauses !!!
|
---|
122 | String lev = level.getValue();
|
---|
123 |
|
---|
124 | if (lev.equalsIgnoreCase("error")) {
|
---|
125 | loglevel = Project.MSG_ERR;
|
---|
126 | } else if (lev.equalsIgnoreCase("warn")) {
|
---|
127 | loglevel = Project.MSG_WARN;
|
---|
128 | } else if (lev.equalsIgnoreCase("info")) {
|
---|
129 | loglevel = Project.MSG_INFO;
|
---|
130 | } else if (lev.equalsIgnoreCase("verbose")) {
|
---|
131 | loglevel = Project.MSG_VERBOSE;
|
---|
132 | } else if (lev.equalsIgnoreCase("debug")) {
|
---|
133 | loglevel = Project.MSG_DEBUG;
|
---|
134 | }
|
---|
135 | }
|
---|
136 |
|
---|
137 | //////////////////////////////////////////////////////////////////////
|
---|
138 | // CORE / MAIN BODY
|
---|
139 |
|
---|
140 | /**
|
---|
141 | * The main execution.
|
---|
142 | * @throws BuildException on error
|
---|
143 | */
|
---|
144 | public void execute() throws BuildException {
|
---|
145 | if (filename == null) {
|
---|
146 | throw new BuildException("No filename specified");
|
---|
147 | }
|
---|
148 |
|
---|
149 | getProject().log("setting a recorder for name " + filename,
|
---|
150 | Project.MSG_DEBUG);
|
---|
151 |
|
---|
152 | // get the recorder entry
|
---|
153 | RecorderEntry recorder = getRecorder(filename, getProject());
|
---|
154 | // set the values on the recorder
|
---|
155 | recorder.setMessageOutputLevel(loglevel);
|
---|
156 | if (start != null) {
|
---|
157 | if (start.booleanValue()) {
|
---|
158 | recorder.reopenFile();
|
---|
159 | recorder.setRecordState(start);
|
---|
160 | } else {
|
---|
161 | recorder.setRecordState(start);
|
---|
162 | recorder.closeFile();
|
---|
163 | }
|
---|
164 | }
|
---|
165 | recorder.setEmacsMode(emacsMode);
|
---|
166 | }
|
---|
167 |
|
---|
168 | //////////////////////////////////////////////////////////////////////
|
---|
169 | // INNER CLASSES
|
---|
170 |
|
---|
171 | /**
|
---|
172 | * A list of possible values for the <code>setAction()</code> method.
|
---|
173 | * Possible values include: start and stop.
|
---|
174 | */
|
---|
175 | public static class ActionChoices extends EnumeratedAttribute {
|
---|
176 | private static final String[] VALUES = {"start", "stop"};
|
---|
177 |
|
---|
178 | /**
|
---|
179 | * @see EnumeratedAttribute#getValues()
|
---|
180 | */
|
---|
181 | public String[] getValues() {
|
---|
182 | return VALUES;
|
---|
183 | }
|
---|
184 | }
|
---|
185 |
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * A list of possible values for the <code>setLoglevel()</code> method.
|
---|
189 | * Possible values include: error, warn, info, verbose, debug.
|
---|
190 | */
|
---|
191 | public static class VerbosityLevelChoices extends EnumeratedAttribute {
|
---|
192 | private static final String[] VALUES = {"error", "warn", "info",
|
---|
193 | "verbose", "debug"};
|
---|
194 |
|
---|
195 | /**
|
---|
196 | * @see EnumeratedAttribute#getValues()
|
---|
197 | */
|
---|
198 | public String[] getValues() {
|
---|
199 | return VALUES;
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 | /**
|
---|
205 | * Gets the recorder that's associated with the passed in name. If the
|
---|
206 | * recorder doesn't exist, then a new one is created.
|
---|
207 | * @param name the name of the recoder
|
---|
208 | * @param proj the current project
|
---|
209 | * @return a recorder
|
---|
210 | * @throws BuildException on error
|
---|
211 | */
|
---|
212 | protected RecorderEntry getRecorder(String name, Project proj)
|
---|
213 | throws BuildException {
|
---|
214 | Object o = recorderEntries.get(name);
|
---|
215 | RecorderEntry entry;
|
---|
216 |
|
---|
217 | if (o == null) {
|
---|
218 | // create a recorder entry
|
---|
219 | entry = new RecorderEntry(name);
|
---|
220 |
|
---|
221 | if (append == null) {
|
---|
222 | entry.openFile(false);
|
---|
223 | } else {
|
---|
224 | entry.openFile(append.booleanValue());
|
---|
225 | }
|
---|
226 | entry.setProject(proj);
|
---|
227 | recorderEntries.put(name, entry);
|
---|
228 | } else {
|
---|
229 | entry = (RecorderEntry) o;
|
---|
230 | }
|
---|
231 | return entry;
|
---|
232 | }
|
---|
233 |
|
---|
234 | }
|
---|
235 |
|
---|