]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java
Update in order to ease reporting
[gpl/argeo-slc.git] / org.argeo.slc.agent / src / main / java / org / argeo / slc / ant / SlcExecutionBuildListener.java
1 package org.argeo.slc.ant;
2
3 import java.util.List;
4 import java.util.Vector;
5
6 import org.apache.log4j.AppenderSkeleton;
7 import org.apache.log4j.LogManager;
8 import org.apache.log4j.spi.LoggingEvent;
9 import org.apache.tools.ant.BuildEvent;
10 import org.apache.tools.ant.Project;
11 import org.argeo.slc.core.process.SlcExecution;
12 import org.argeo.slc.core.process.SlcExecutionNotifier;
13 import org.argeo.slc.core.process.SlcExecutionStep;
14 import org.argeo.slc.ws.process.WebServiceSlcExecutionNotifier;
15 import org.springframework.context.ApplicationContext;
16 import org.springframework.context.support.AbstractApplicationContext;
17
18 public class SlcExecutionBuildListener extends AppenderSkeleton implements
19 ProjectRelatedBuildListener {
20 public static final String ANT_TYPE = "org.apache.tools.ant";
21 public static final String SLC_ANT_TYPE = "org.argeo.slc.ant";
22
23 public static final String REF_SLC_EXECUTION = "slcExecution";
24
25 private Project project;
26
27 // to avoid stack overflow when logging for log4j
28 private boolean isLogging = false;
29
30 private List<SlcExecutionNotifier> notifiers = new Vector<SlcExecutionNotifier>();
31
32 private boolean currentStepNotified = true;
33
34 // CUSTOMIZATIONS
35 private boolean logBeforeFirstTarget = false;
36 private boolean firstTargetStarted = false;
37
38 private boolean logTaskStartFinish = true;
39
40 public void init(Project project) {
41 if (this.project != null) {
42 throw new SlcAntException("Build listener already initialized");
43 }
44
45 this.project = project;
46
47 if (!LogManager.getRootLogger().isAttached(this)) {
48 LogManager.getRootLogger().addAppender(this);
49 }
50
51 SlcExecution slcExecution = (SlcExecution) project
52 .getReference(REF_SLC_EXECUTION);
53 if (slcExecution == null)
54 throw new SlcAntException("No SLC Execution registered.");
55
56 for (SlcExecutionNotifier notifier : notifiers) {
57 notifier.newExecution(slcExecution);
58 }
59
60 }
61
62 public void buildStarted(BuildEvent event) {
63 }
64
65 public void buildFinished(BuildEvent event) {
66 SlcExecution slcExecution = getSlcExecution(event);
67 String oldStatus = slcExecution.getStatus();
68 slcExecution.setStatus(SlcExecution.STATUS_FINISHED);
69
70 for (SlcExecutionNotifier notifier : notifiers) {
71 notifier.updateStatus(slcExecution, oldStatus, slcExecution
72 .getStatus());
73 }
74
75 // AbstractApplicationContext context = (AbstractApplicationContext) getProject()
76 // .getReference(SlcProjectHelper.REF_ROOT_CONTEXT);
77 // if (context != null)
78 // context.close();
79 }
80
81 public void messageLogged(BuildEvent event) {
82 if (!shouldLog())
83 return;
84
85 SlcExecution slcExecution = getSlcExecution(event);
86 if (slcExecution != null) {
87 if (currentStepNotified) {
88 slcExecution.getSteps().add(
89 new SlcExecutionStep("LOG", event.getMessage()));
90 notifyStep(slcExecution, slcExecution.currentStep());
91 currentStepNotified = true;
92 } else {
93 slcExecution.currentStep().addLog(event.getMessage());
94 }
95 } else {
96 // TODO: log before initialization?
97 }
98 }
99
100 public void targetStarted(BuildEvent event) {
101 if (!firstTargetStarted)
102 firstTargetStarted = true;
103
104 addLogStep(event, "Target " + event.getTarget().getName() + " started");
105 }
106
107 public void targetFinished(BuildEvent event) {
108 addLogStep(event, "Target " + event.getTarget().getName() + " finished");
109 }
110
111 public void taskStarted(BuildEvent event) {
112 if (!shouldLog())
113 return;
114
115 SlcExecution slcExecution = getSlcExecution(event);
116 if (!currentStepNotified) {
117 notifyStep(slcExecution, slcExecution.currentStep());
118 currentStepNotified = true;
119 }
120
121 String msg = null;
122 if (logTaskStartFinish)
123 msg = "Task " + event.getTask().getTaskName() + " started";
124
125 slcExecution.getSteps().add(new SlcExecutionStep("LOG", msg));
126
127 currentStepNotified = false;
128 }
129
130 public void taskFinished(BuildEvent event) {
131 if (!shouldLog())
132 return;
133
134 SlcExecution slcExecution = getSlcExecution(event);
135 if (!currentStepNotified) {
136
137 if (logTaskStartFinish)
138 slcExecution.currentStep().addLog(
139 "Task " + event.getTask().getTaskName() + " finished");
140
141 notifyStep(slcExecution, slcExecution.currentStep());
142 currentStepNotified = true;
143 }
144 }
145
146 public void setNotifiers(List<SlcExecutionNotifier> notifiers) {
147 this.notifiers = notifiers;
148 }
149
150 protected SlcExecution getSlcExecution(BuildEvent event) {
151 Project projectEvt = event.getProject();
152 if (!projectEvt.equals(project))
153 throw new SlcAntException("Event project " + projectEvt
154 + " not consistent with listener project " + project);
155
156 SlcExecution slcExecution = (SlcExecution) project
157 .getReference(REF_SLC_EXECUTION);
158
159 if (slcExecution == null)
160 throw new SlcAntException("No SLC Execution registered.");
161 return slcExecution;
162 }
163
164 protected void addLogStep(BuildEvent event, String msg) {
165 SlcExecution slcExecution = getSlcExecution(event);
166 slcExecution.getSteps().add(new SlcExecutionStep("LOG", msg));
167
168 notifyStep(slcExecution, slcExecution.currentStep());
169 currentStepNotified = true;
170 }
171
172 protected void notifyStep(SlcExecution slcExecution, SlcExecutionStep step) {
173 Vector<SlcExecutionStep> additionalSteps = new Vector<SlcExecutionStep>();
174 additionalSteps.add(step);
175 notifySteps(slcExecution, additionalSteps);
176 }
177
178 protected void notifySteps(SlcExecution slcExecution,
179 List<SlcExecutionStep> additionalSteps) {
180 for (SlcExecutionNotifier notifier : notifiers) {
181 notifier.addSteps(slcExecution, additionalSteps);
182 }
183 }
184
185 /* Log4j methods */
186
187 @Override
188 protected void append(LoggingEvent event) {
189 if (isLogging) {
190 // avoid StackOverflow if notification calls Log4j itself.
191 return;
192 }
193
194 // FIXME: make it more generic
195 if (event.getLoggerName().equals(
196 WebServiceSlcExecutionNotifier.class.getName())) {
197 return;
198 }
199
200 isLogging = true;
201
202 try {
203 SlcExecution slcExecution = (SlcExecution) project
204 .getReference(REF_SLC_EXECUTION);
205 if (slcExecution != null) {
206 if (currentStepNotified) {
207 slcExecution.getSteps().add(
208 new SlcExecutionStep("LOG", event.getMessage()
209 .toString()));
210 currentStepNotified = false;
211 }
212 slcExecution.currentStep()
213 .addLog(event.getMessage().toString());
214 } else {
215 // TODO: log before initialization?
216 }
217 } finally {
218 isLogging = false;
219 }
220
221 }
222
223 protected boolean shouldLog() {
224 return logBeforeFirstTarget || firstTargetStarted;
225 }
226
227 @Override
228 public void close() {
229 }
230
231 @Override
232 public boolean requiresLayout() {
233 return false;
234 }
235
236 public Project getProject() {
237 return project;
238 }
239
240 }