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