1 package org.apache.maven.continuum.notification.wagon;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.annotation.Resource;
28
29 import org.apache.maven.artifact.manager.WagonManager;
30 import org.apache.maven.artifact.repository.ArtifactRepository;
31 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
32 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
33 import org.apache.maven.continuum.ContinuumException;
34 import org.apache.maven.continuum.configuration.ConfigurationException;
35 import org.apache.maven.continuum.configuration.ConfigurationService;
36 import org.apache.maven.continuum.model.project.BuildDefinition;
37 import org.apache.maven.continuum.model.project.BuildResult;
38 import org.apache.maven.continuum.model.project.Project;
39 import org.apache.maven.continuum.model.project.ProjectNotifier;
40 import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
41 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
42 import org.apache.maven.continuum.notification.MessageContext;
43 import org.apache.maven.continuum.notification.NotificationException;
44 import org.apache.maven.model.DistributionManagement;
45 import org.apache.maven.model.Site;
46 import org.apache.maven.profiles.DefaultProfileManager;
47 import org.apache.maven.profiles.ProfileManager;
48 import org.apache.maven.project.MavenProject;
49 import org.apache.maven.project.MavenProjectBuilder;
50 import org.apache.maven.project.ProjectBuildingException;
51 import org.apache.maven.settings.MavenSettingsBuilder;
52 import org.apache.maven.settings.Proxy;
53 import org.apache.maven.settings.Server;
54 import org.apache.maven.settings.Settings;
55 import org.apache.maven.wagon.CommandExecutionException;
56 import org.apache.maven.wagon.CommandExecutor;
57 import org.apache.maven.wagon.ConnectionException;
58 import org.apache.maven.wagon.ResourceDoesNotExistException;
59 import org.apache.maven.wagon.TransferFailedException;
60 import org.apache.maven.wagon.UnsupportedProtocolException;
61 import org.apache.maven.wagon.Wagon;
62 import org.apache.maven.wagon.authentication.AuthenticationException;
63 import org.apache.maven.wagon.authentication.AuthenticationInfo;
64 import org.apache.maven.wagon.authorization.AuthorizationException;
65 import org.apache.maven.wagon.observers.Debug;
66 import org.apache.maven.wagon.proxy.ProxyInfo;
67 import org.apache.maven.wagon.repository.Repository;
68 import org.codehaus.plexus.PlexusConstants;
69 import org.codehaus.plexus.PlexusContainer;
70 import org.codehaus.plexus.context.Context;
71 import org.codehaus.plexus.context.ContextException;
72 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
73 import org.codehaus.plexus.util.StringUtils;
74 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77 import org.springframework.stereotype.Service;
78
79
80
81
82
83 @Service("notifier#wagon")
84 public class WagonContinuumNotifier
85 extends AbstractContinuumNotifier
86 implements Contextualizable
87 {
88 public static final String BUILD_OUTPUT_FILE_NAME = "buildresult.txt";
89
90 private static final Logger log = LoggerFactory.getLogger( WagonContinuumNotifier.class );
91
92 @Resource
93 private ConfigurationService configurationService;
94
95 @Resource
96 private WagonManager wagonManager;
97
98 @Resource
99 private MavenProjectBuilder projectBuilder;
100
101 @Resource
102 private MavenSettingsBuilder settingsBuilder;
103
104
105
106
107 private String localRepository;
108
109 private Settings settings;
110
111 private ProfileManager profileManager;
112
113 private PlexusContainer container;
114
115 public String getType()
116 {
117 return "wagon";
118 }
119
120 public void sendMessage( String messageId, MessageContext context )
121 throws NotificationException
122 {
123 Project project = context.getProject();
124
125 List<ProjectNotifier> notifiers = context.getNotifiers();
126
127 BuildResult build = context.getBuildResult();
128
129 BuildDefinition buildDefinition = context.getBuildDefinition();
130
131
132
133
134 if ( build == null )
135 {
136 return;
137 }
138
139
140
141
142 try
143 {
144
145
146
147 MavenProject mavenProject = getMavenProject( project, buildDefinition );
148
149 if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
150 {
151 for ( ProjectNotifier notifier : notifiers )
152 {
153 buildComplete( notifier, build, mavenProject );
154 }
155 }
156 }
157 catch ( ContinuumException e )
158 {
159 throw new NotificationException( "Error while notifiying.", e );
160 }
161 }
162
163 private void buildComplete( ProjectNotifier notifier, BuildResult build, MavenProject mavenProject )
164 throws ContinuumException
165 {
166 String id;
167 String url;
168
169 Map<String, String> configuration = notifier.getConfiguration();
170
171 if ( configuration.containsKey( "url" ) )
172 {
173 url = configuration.get( "url" );
174 id = configuration.get( "id" );
175 }
176 else
177 {
178 DistributionManagement distributionManagement = mavenProject.getDistributionManagement();
179
180 if ( distributionManagement == null )
181 {
182 throw new ContinuumException( "Missing distribution management information in the project." );
183 }
184
185 Site site = distributionManagement.getSite();
186 if ( site == null )
187 {
188 throw new ContinuumException(
189 "Missing site information in the distribution management element in the project." );
190 }
191
192 url = site.getUrl();
193 id = site.getId();
194 }
195
196 if ( url == null )
197 {
198 throw new ContinuumException( "The URL to the site is not defined." );
199 }
200
201 Repository repository = new Repository( id, url );
202
203 Wagon wagon;
204 try
205 {
206 wagon = wagonManager.getWagon( repository.getProtocol() );
207 }
208 catch ( UnsupportedProtocolException e )
209 {
210 throw new ContinuumException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
211 }
212
213 if ( !wagon.supportsDirectoryCopy() )
214 {
215 throw new ContinuumException(
216 "Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
217 }
218
219 try
220 {
221 if ( log.isDebugEnabled() )
222 {
223 Debug debug = new Debug();
224
225 wagon.addSessionListener( debug );
226 wagon.addTransferListener( debug );
227 }
228
229 ProxyInfo proxyInfo = getProxyInfo( repository );
230
231 if ( proxyInfo != null )
232 {
233 wagon.connect( repository, getAuthenticationInfo( id ), proxyInfo );
234 }
235 else
236 {
237 wagon.connect( repository, getAuthenticationInfo( id ) );
238 }
239
240 File buildOutputFile = configurationService.getBuildOutputFile( build.getId(), build.getProject().getId() );
241
242 wagon.put( buildOutputFile, BUILD_OUTPUT_FILE_NAME );
243
244
245
246 if ( wagon instanceof CommandExecutor )
247 {
248 CommandExecutor exec = (CommandExecutor) wagon;
249 exec.executeCommand( "chmod -Rf g+w " + repository.getBasedir() );
250 }
251 }
252 catch ( ConfigurationException e )
253 {
254 throw new ContinuumException( "Error uploading build results to deployed site.", e );
255 }
256 catch ( ResourceDoesNotExistException e )
257 {
258 throw new ContinuumException( "Error uploading site", e );
259 }
260 catch ( TransferFailedException e )
261 {
262 throw new ContinuumException( "Error uploading site", e );
263 }
264 catch ( AuthorizationException e )
265 {
266 throw new ContinuumException( "Error uploading site", e );
267 }
268 catch ( ConnectionException e )
269 {
270 throw new ContinuumException( "Error uploading site", e );
271 }
272 catch ( AuthenticationException e )
273 {
274 throw new ContinuumException( "Error uploading site", e );
275 }
276 catch ( CommandExecutionException e )
277 {
278 throw new ContinuumException( "Error uploading site", e );
279 }
280 finally
281 {
282 try
283 {
284 wagon.disconnect();
285 }
286 catch ( ConnectionException e )
287 {
288 log.error( "Error disconnecting wagon - ignored", e );
289 }
290 }
291 }
292
293 private MavenProject getMavenProject( Project project, BuildDefinition buildDefinition )
294 throws ContinuumException
295 {
296 File projectWorkingDir =
297 new File( configurationService.getWorkingDirectory(), Integer.toString( project.getId() ) );
298 File pomFile = new File( projectWorkingDir, buildDefinition.getBuildFile() );
299
300 MavenProject mavenProject;
301
302 try
303 {
304 mavenProject = projectBuilder.build( pomFile, getLocalRepository(), getProfileManager() );
305 }
306 catch ( ProjectBuildingException e )
307 {
308 throw new ContinuumException( "Unable to acquire the MavenProject in " + pomFile.getAbsolutePath(), e );
309 }
310
311 return mavenProject;
312 }
313
314 private Settings getSettings()
315 {
316 if ( settings == null )
317 {
318 try
319 {
320 settings = settingsBuilder.buildSettings();
321 }
322 catch ( IOException e )
323 {
324 log.error( "Failed to get Settings", e );
325 }
326 catch ( XmlPullParserException e )
327 {
328 log.error( "Failed to get Settings", e );
329 }
330 }
331
332 return settings;
333 }
334
335 private ArtifactRepository getLocalRepository()
336 {
337 String repo = localRepository;
338
339 if ( getSettings() != null && !StringUtils.isEmpty( getSettings().getLocalRepository() ) )
340 {
341 repo = getSettings().getLocalRepository();
342 }
343
344 return new DefaultArtifactRepository( "local-repository", "file://" + repo, new DefaultRepositoryLayout() );
345 }
346
347 private ProfileManager getProfileManager()
348 {
349 if ( profileManager == null )
350 {
351 profileManager = new DefaultProfileManager( container, getSettings() );
352 }
353
354 return profileManager;
355 }
356
357 public void contextualize( Context context )
358 throws ContextException
359 {
360 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
361 }
362
363 private ProxyInfo getProxyInfo( Repository repository )
364 {
365 Settings settings = getSettings();
366 if ( settings.getProxies() != null && !settings.getProxies().isEmpty() )
367 {
368 for ( Proxy p : (List<Proxy>) settings.getProxies() )
369 {
370 wagonManager.addProxy( p.getProtocol(), p.getHost(), p.getPort(), p.getUsername(), p.getPassword(),
371 p.getNonProxyHosts() );
372 }
373 }
374 return wagonManager.getProxy( repository.getProtocol() );
375 }
376
377 private AuthenticationInfo getAuthenticationInfo( String repositoryId )
378 {
379 Settings settings = getSettings();
380 Server server = settings.getServer( repositoryId );
381
382 if ( server == null )
383 {
384 return null;
385 }
386
387 wagonManager.addAuthenticationInfo( repositoryId, server.getUsername(), server.getPassword(),
388 server.getPrivateKey(), server.getPassphrase() );
389 return wagonManager.getAuthenticationInfo( repositoryId );
390 }
391 }