1 package org.apache.maven.continuum.notification;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.continuum.configuration.ContinuumConfigurationException;
23 import org.apache.continuum.dao.BuildResultDao;
24 import org.apache.continuum.dao.ProjectDao;
25 import org.apache.continuum.dao.ProjectScmRootDao;
26 import org.apache.continuum.model.project.ProjectScmRoot;
27 import org.apache.maven.continuum.ContinuumException;
28 import org.apache.maven.continuum.configuration.ConfigurationException;
29 import org.apache.maven.continuum.configuration.ConfigurationLoadingException;
30 import org.apache.maven.continuum.configuration.ConfigurationService;
31 import org.apache.maven.continuum.model.project.BuildDefinition;
32 import org.apache.maven.continuum.model.project.BuildResult;
33 import org.apache.maven.continuum.model.project.Project;
34 import org.apache.maven.continuum.model.project.ProjectGroup;
35 import org.apache.maven.continuum.model.project.ProjectNotifier;
36 import org.apache.maven.continuum.project.ContinuumProjectState;
37 import org.apache.maven.continuum.store.ContinuumStoreException;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import java.util.List;
42 import javax.annotation.Resource;
43
44 public abstract class AbstractContinuumNotifier
45 implements Notifier
46 {
47 public static final String ADDRESS_FIELD = "address";
48
49 public static final String COMMITTER_FIELD = "committers";
50
51 public static final String DEVELOPER_FIELD = "developers";
52
53 private static final Logger log = LoggerFactory.getLogger( AbstractContinuumNotifier.class );
54
55 @Resource
56 private ConfigurationService configurationService;
57
58 @Resource
59 private BuildResultDao buildResultDao;
60
61 @Resource
62 private ProjectDao projectDao;
63
64 @Resource
65 private ProjectScmRootDao projectScmRootDao;
66
67 private boolean alwaysSend = false;
68
69 protected String getBuildOutput( Project project, BuildResult buildResult )
70 {
71 if ( buildResult == null )
72 {
73 return "";
74 }
75 try
76 {
77 if ( buildResult.getEndTime() != 0 )
78 {
79 return configurationService.getBuildOutput( buildResult.getId(), project.getId() );
80 }
81 else
82 {
83 return "";
84 }
85 }
86 catch ( ConfigurationException e )
87 {
88 String msg = "Error while population the notification context.";
89 log.error( msg, e );
90 return msg;
91 }
92 }
93
94
95
96
97
98
99
100
101
102
103 public String getReportUrl( Project project, BuildResult build, ConfigurationService configurationService )
104 throws ContinuumException
105 {
106 try
107 {
108 if ( !configurationService.isLoaded() )
109 {
110 configurationService.reload();
111 }
112
113 StringBuffer buf = new StringBuffer( configurationService.getUrl() );
114
115 if ( project != null && build != null )
116 {
117 if ( !buf.toString().endsWith( "/" ) )
118 {
119 buf.append( "/" );
120 }
121
122 buf.append( "buildResult.action?buildId=" ).append( build.getId() ).append( "&projectId=" ).append(
123 project.getId() );
124 }
125
126 return buf.toString();
127 }
128 catch ( ConfigurationLoadingException e )
129 {
130 throw new ContinuumException( "Can't obtain the base url from configuration.", e );
131 }
132 catch ( ContinuumConfigurationException e )
133 {
134 throw new ContinuumException( "Can't obtain the base url from configuration.", e );
135 }
136 }
137
138 public String getReportUrl( ProjectGroup projectGroup, ProjectScmRoot projectScmRoot,
139 ConfigurationService configurationService )
140 throws ContinuumException
141 {
142 try
143 {
144 if ( !configurationService.isLoaded() )
145 {
146 configurationService.reload();
147 }
148
149 StringBuffer buf = new StringBuffer( configurationService.getUrl() );
150
151 if ( projectGroup != null && projectScmRoot != null )
152 {
153 if ( !buf.toString().endsWith( "/" ) )
154 {
155 buf.append( "/" );
156 }
157
158 buf.append( "scmResult.action?projectScmRootId=" ).append( projectScmRoot.getId() ).append(
159 "&projectGroupId=" ).append( projectGroup.getId() );
160 }
161
162 return buf.toString();
163 }
164 catch ( ConfigurationLoadingException e )
165 {
166 throw new ContinuumException( "Can't obtain the base url from configuration.", e );
167 }
168 catch ( ContinuumConfigurationException e )
169 {
170 throw new ContinuumException( "Can't obtain the base url from configuration.", e );
171 }
172 }
173
174
175
176
177
178
179
180
181
182 public boolean shouldNotify( BuildResult build, BuildResult previousBuild, ProjectNotifier projectNotifier )
183 {
184 if ( projectNotifier == null )
185 {
186 projectNotifier = new ProjectNotifier();
187 }
188
189 if ( build == null )
190 {
191 return false;
192 }
193
194 if ( alwaysSend )
195 {
196 return true;
197 }
198
199 if ( build.getState() == ContinuumProjectState.FAILED && projectNotifier.isSendOnFailure() )
200 {
201 return true;
202 }
203
204 if ( build.getState() == ContinuumProjectState.ERROR && projectNotifier.isSendOnError() )
205 {
206 return true;
207 }
208
209
210 if ( previousBuild == null )
211 {
212 if ( build.getState() == ContinuumProjectState.ERROR )
213 {
214 return projectNotifier.isSendOnError();
215 }
216
217 if ( build.getState() == ContinuumProjectState.FAILED )
218 {
219 return projectNotifier.isSendOnFailure();
220 }
221
222 if ( build.getState() == ContinuumProjectState.OK )
223 {
224 return projectNotifier.isSendOnSuccess();
225 }
226
227 return build.getState() != ContinuumProjectState.WARNING || projectNotifier.isSendOnWarning();
228
229 }
230
231
232 if ( log.isDebugEnabled() )
233 {
234 log.debug(
235 "Current build state: " + build.getState() + ", previous build state: " + previousBuild.getState() );
236 }
237
238 if ( build.getState() != previousBuild.getState() )
239 {
240 if ( build.getState() == ContinuumProjectState.ERROR )
241 {
242 return projectNotifier.isSendOnError();
243 }
244
245 if ( build.getState() == ContinuumProjectState.FAILED )
246 {
247 return projectNotifier.isSendOnFailure();
248 }
249
250 if ( build.getState() == ContinuumProjectState.OK )
251 {
252 return projectNotifier.isSendOnSuccess();
253 }
254
255 return build.getState() != ContinuumProjectState.WARNING || projectNotifier.isSendOnWarning();
256
257 }
258
259 log.info( "Same state, not sending message." );
260
261 return false;
262 }
263
264 public boolean shouldNotify( ProjectScmRoot projectScmRoot, ProjectNotifier projectNotifier )
265 {
266 if ( projectNotifier == null )
267 {
268 projectNotifier = new ProjectNotifier();
269 }
270
271 return projectScmRoot != null && ( alwaysSend ||
272 projectScmRoot.getState() == ContinuumProjectState.ERROR && projectNotifier.isSendOnScmFailure() &&
273 projectScmRoot.getOldState() != projectScmRoot.getState() );
274
275 }
276
277 protected BuildResult getPreviousBuild( Project project, BuildDefinition buildDef, BuildResult currentBuild )
278 throws NotificationException
279 {
280 List<BuildResult> builds;
281 try
282 {
283 if ( buildDef != null )
284 {
285 builds = buildResultDao.getBuildResultsByBuildDefinition( project.getId(), buildDef.getId(), 0, 2 );
286
287 if ( builds.size() < 2 )
288 {
289 return null;
290 }
291
292 BuildResult build = builds.get( 0 );
293 if ( currentBuild != null && build.getId() != currentBuild.getId() )
294 {
295 throw new NotificationException(
296 "INTERNAL ERROR: The current build wasn't the first in the build list. " + "Current build: '" +
297 currentBuild.getId() + "', " + "first build: '" + build.getId() + "'." );
298 }
299 else
300 {
301 return builds.get( 1 );
302 }
303 }
304 else
305 {
306
307 if ( project.getId() > 0 )
308 {
309 project = projectDao.getProjectWithBuilds( project.getId() );
310 }
311 builds = project.getBuildResults();
312
313 if ( builds.size() < 2 )
314 {
315 return null;
316 }
317
318 BuildResult build = builds.get( builds.size() - 1 );
319
320 if ( currentBuild != null && build.getId() != currentBuild.getId() )
321 {
322 throw new NotificationException(
323 "INTERNAL ERROR: The current build wasn't the first in the build list. " + "Current build: '" +
324 currentBuild.getId() + "', " + "first build: '" + build.getId() + "'." );
325 }
326
327 return builds.get( builds.size() - 2 );
328 }
329 }
330 catch ( ContinuumStoreException e )
331 {
332 throw new NotificationException( "Unable to obtain project builds", e );
333 }
334 }
335
336 protected String generateMessage( Project project, BuildResult build, ConfigurationService configurationService )
337 throws NotificationException
338 {
339 int state = project.getState();
340
341 if ( build != null )
342 {
343 state = build.getState();
344 }
345
346 String message;
347
348 if ( state == ContinuumProjectState.OK )
349 {
350 message = "BUILD SUCCESSFUL: " + project.getName();
351 }
352 else if ( state == ContinuumProjectState.FAILED )
353 {
354 message = "BUILD FAILURE: " + project.getName();
355 }
356 else if ( state == ContinuumProjectState.ERROR )
357 {
358 message = "BUILD ERROR: " + project.getName();
359 }
360 else
361 {
362 log.warn( "Unknown build state " + state + " for project " + project.getId() );
363
364 message = "ERROR: Unknown build state " + state + " for " + project.getName() + " project";
365 }
366
367 try
368 {
369 return message + " " + getReportUrl( project, build, configurationService );
370 }
371 catch ( ContinuumException e )
372 {
373 throw new NotificationException( "Cannot generate message", e );
374 }
375 }
376
377 protected String generateMessage( ProjectScmRoot projectScmRoot, ConfigurationService configurationService )
378 throws NotificationException
379 {
380 int state = projectScmRoot.getState();
381 String scmRootAddress = projectScmRoot.getScmRootAddress();
382
383 String message;
384
385 if ( state == ContinuumProjectState.UPDATED )
386 {
387 message = "PREPARE BUILD SUCCESSFUL: " + scmRootAddress;
388 }
389 else if ( state == ContinuumProjectState.ERROR )
390 {
391 message = "PREPARE BUILD ERROR: " + scmRootAddress;
392 }
393 else
394 {
395 log.warn( "Unknown prepare build state " + state + " for SCM root URL " + scmRootAddress );
396
397 message = "ERROR: Unknown prepare build state " + state + " for SCM root URL" + scmRootAddress;
398 }
399
400 try
401 {
402 return message + " " +
403 getReportUrl( projectScmRoot.getProjectGroup(), projectScmRoot, configurationService );
404 }
405 catch ( ContinuumException e )
406 {
407 throw new NotificationException( "Cannot generate message", e );
408 }
409 }
410 }