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