1 package org.apache.maven.shared.release.phase;
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.io.Reader;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Stack;
32
33 import org.apache.commons.lang.SystemUtils;
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.ArtifactUtils;
36 import org.apache.maven.artifact.factory.ArtifactFactory;
37 import org.apache.maven.artifact.manager.WagonManager;
38 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
39 import org.apache.maven.artifact.repository.ArtifactRepository;
40 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
41 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
42 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
43 import org.apache.maven.artifact.resolver.ArtifactCollector;
44 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
45 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
46 import org.apache.maven.artifact.versioning.VersionRange;
47 import org.apache.maven.model.Dependency;
48 import org.apache.maven.model.DependencyManagement;
49 import org.apache.maven.model.Profile;
50 import org.apache.maven.model.Repository;
51 import org.apache.maven.profiles.DefaultProfileManager;
52 import org.apache.maven.profiles.ProfileManager;
53 import org.apache.maven.project.MavenProject;
54 import org.apache.maven.project.MavenProjectBuilder;
55 import org.apache.maven.project.ProjectBuildingException;
56 import org.apache.maven.project.ProjectSorter;
57 import org.apache.maven.shared.release.util.ReleaseUtil;
58 import org.codehaus.plexus.PlexusTestCase;
59 import org.codehaus.plexus.context.ContextException;
60 import org.codehaus.plexus.context.DefaultContext;
61 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
62 import org.codehaus.plexus.util.FileUtils;
63 import org.codehaus.plexus.util.IOUtil;
64 import org.codehaus.plexus.util.ReaderFactory;
65 import org.codehaus.plexus.util.StringUtils;
66 import org.custommonkey.xmlunit.Diff;
67 import org.custommonkey.xmlunit.Difference;
68 import org.custommonkey.xmlunit.DifferenceListener;
69 import org.custommonkey.xmlunit.XMLAssert;
70 import org.custommonkey.xmlunit.XMLUnit;
71 import org.w3c.dom.Node;
72 import org.xml.sax.SAXException;
73
74
75
76
77
78
79 public abstract class AbstractReleaseTestCase
80 extends PlexusTestCase
81 {
82 protected MavenProjectBuilder projectBuilder;
83
84 protected ArtifactRepository localRepository;
85
86 protected ReleasePhase phase;
87
88 private static final DefaultContext EMPTY_CONTEXT = new DefaultContext()
89 {
90 public Object get( Object key )
91 throws ContextException
92 {
93 return null;
94 }
95 };
96
97 protected void setUp()
98 throws Exception
99 {
100 super.setUp();
101
102 projectBuilder = (MavenProjectBuilder) lookup( MavenProjectBuilder.ROLE );
103
104 ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, "default" );
105 String localRepoPath = getTestFile( "target/local-repository" ).getAbsolutePath().replace( '\\', '/' );
106 localRepository = new DefaultArtifactRepository( "local", "file://" + localRepoPath, layout );
107 }
108
109 protected void tearDown()
110 throws Exception
111 {
112
113 ( (Contextualizable) projectBuilder ).contextualize( EMPTY_CONTEXT );
114 ( (Contextualizable) lookup( WagonManager.ROLE ) ).contextualize( EMPTY_CONTEXT );
115
116 super.tearDown();
117 }
118
119 private Map<String,Artifact> createManagedVersionMap( String projectId, DependencyManagement dependencyManagement,
120 ArtifactFactory artifactFactory )
121 throws ProjectBuildingException
122 {
123 Map<String,Artifact> map;
124 if ( dependencyManagement != null && dependencyManagement.getDependencies() != null )
125 {
126 map = new HashMap<String,Artifact>();
127 for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
128 {
129 Dependency d = (Dependency) i.next();
130
131 try
132 {
133 VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
134 Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(),
135 versionRange, d.getType(),
136 d.getClassifier(), d.getScope() );
137 map.put( d.getManagementKey(), artifact );
138 }
139 catch ( InvalidVersionSpecificationException e )
140 {
141 throw new ProjectBuildingException( projectId, "Unable to parse version '" + d.getVersion() +
142 "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e );
143 }
144 }
145 }
146 else
147 {
148 map = Collections.emptyMap();
149 }
150 return map;
151 }
152
153 protected List<MavenProject> createReactorProjects( String path, String subpath )
154 throws Exception
155 {
156 return createReactorProjects( path, path, subpath );
157 }
158
159 protected List<MavenProject> createReactorProjects( String path, String targetPath, String subpath )
160 throws Exception
161 {
162 File testFile = getTestFile( "target/test-classes/projects/" + path + subpath + "/pom.xml" );
163 Stack<File> projectFiles = new Stack<File>();
164 projectFiles.push( testFile );
165
166 List<DefaultArtifactRepository> repos =
167 Collections.singletonList( new DefaultArtifactRepository( "central", getRemoteRepositoryURL(), new DefaultRepositoryLayout() ) );
168
169 Repository repository = new Repository();
170 repository.setId( "central" );
171 repository.setUrl( getRemoteRepositoryURL() );
172
173 ProfileManager profileManager = new DefaultProfileManager( getContainer() );
174 Profile profile = new Profile();
175 profile.setId( "profile" );
176 profile.addRepository( repository );
177 profileManager.addProfile( profile );
178 profileManager.activateAsDefault( profile.getId() );
179
180 List<MavenProject> reactorProjects = new ArrayList<MavenProject>();
181 while ( !projectFiles.isEmpty() )
182 {
183 File file = (File) projectFiles.pop();
184
185
186 String filePath = file.getPath();
187 int index = filePath.indexOf( "test-classes" ) + "test-classes".length() + 1;
188 filePath = filePath.substring( index ).replace( '\\', '/' );
189
190 File newFile = getTestFile( "target/test-classes/" + StringUtils.replace( filePath, path, targetPath ) );
191 FileUtils.copyFile( getTestFile( "src/test/resources/" + filePath ), newFile );
192
193 MavenProject project = projectBuilder.build( newFile, localRepository, profileManager );
194
195 for ( Iterator i = project.getModules().iterator(); i.hasNext(); )
196 {
197 String module = (String) i.next();
198
199 projectFiles.push( new File( file.getParentFile(), module + "/pom.xml" ) );
200 }
201
202 reactorProjects.add( project );
203 }
204
205 ProjectSorter sorter = new ProjectSorter( reactorProjects );
206
207 reactorProjects = sorter.getSortedProjects();
208
209 ArtifactFactory artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
210 ArtifactCollector artifactCollector = (ArtifactCollector) lookup( ArtifactCollector.class.getName() );
211 ArtifactMetadataSource artifactMetadataSource = (ArtifactMetadataSource) lookup( ArtifactMetadataSource.ROLE );
212
213
214 for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
215 {
216 MavenProject project = (MavenProject) i.next();
217
218 project.setRemoteArtifactRepositories( repos );
219 project.setPluginArtifactRepositories( repos );
220
221 Artifact projectArtifact = project.getArtifact();
222
223 Map managedVersions = createManagedVersionMap(
224 ArtifactUtils.versionlessKey( projectArtifact.getGroupId(), projectArtifact.getArtifactId() ),
225 project.getDependencyManagement(), artifactFactory );
226
227 project.setDependencyArtifacts( project.createArtifacts( artifactFactory, null, null ) );
228
229 ArtifactResolutionResult result = artifactCollector.collect( project.getDependencyArtifacts(),
230 projectArtifact, managedVersions,
231 localRepository, repos, artifactMetadataSource,
232 null, Collections.EMPTY_LIST );
233
234 project.setArtifacts( result.getArtifacts() );
235 }
236
237 return reactorProjects;
238 }
239
240 protected static Map<String,MavenProject> getProjectsAsMap( List<MavenProject> reactorProjects )
241 {
242 Map<String,MavenProject> map = new HashMap<String,MavenProject>();
243 for ( Iterator<MavenProject> i = reactorProjects.iterator(); i.hasNext(); )
244 {
245 MavenProject project = (MavenProject) i.next();
246
247 map.put( ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() ), project );
248 }
249 return map;
250 }
251
252 protected boolean comparePomFiles( List<MavenProject> reactorProjects )
253 throws IOException
254 {
255 return comparePomFiles( reactorProjects, true );
256 }
257
258 protected boolean comparePomFiles( List<MavenProject> reactorProjects, boolean normalizeLineEndings )
259 throws IOException
260 {
261 comparePomFiles( reactorProjects, "", normalizeLineEndings );
262
263
264 return true;
265 }
266
267 protected void comparePomFiles( List<MavenProject> reactorProjects, String expectedFileSuffix )
268 throws IOException
269 {
270 comparePomFiles( reactorProjects, expectedFileSuffix, true );
271 }
272
273 protected void comparePomFiles( List<MavenProject> reactorProjects, String expectedFileSuffix, boolean normalizeLineEndings )
274 throws IOException
275 {
276 for ( Iterator<MavenProject> i = reactorProjects.iterator(); i.hasNext(); )
277 {
278 MavenProject project = i.next();
279
280 comparePomFiles( project, expectedFileSuffix, normalizeLineEndings );
281 }
282 }
283
284 protected void comparePomFiles( MavenProject project, String expectedFileSuffix )
285 throws IOException
286 {
287 comparePomFiles( project, expectedFileSuffix, true );
288 }
289
290 protected void comparePomFiles( MavenProject project, String expectedFileSuffix, boolean normalizeLineEndings )
291 throws IOException
292 {
293 File actualFile = project.getFile();
294 File expectedFile = new File( actualFile.getParentFile(), "expected-pom" + expectedFileSuffix + ".xml" );
295
296 comparePomFiles( expectedFile, actualFile, normalizeLineEndings );
297 }
298
299 protected void comparePomFiles( File expectedFile, File actualFile )
300 throws IOException
301 {
302 comparePomFiles( expectedFile, actualFile, true );
303 }
304
305 protected void comparePomFiles( File expectedFile, File actualFile, boolean normalizeLineEndings )
306 throws IOException
307 {
308 Reader expected = null;
309 Reader actual = null;
310 try
311 {
312 expected = ReaderFactory.newXmlReader( expectedFile );
313 actual = ReaderFactory.newXmlReader( actualFile );
314
315 StringBuffer sb = new StringBuffer( "Check the transformed POM " + actualFile );
316 sb.append( SystemUtils.LINE_SEPARATOR );
317
318 final String remoteRepositoryURL = getRemoteRepositoryURL();
319
320 XMLUnit.setNormalizeWhitespace( true );
321
322 Diff diff = XMLUnit.compareXML( expected, actual );
323
324 diff.overrideDifferenceListener( new DifferenceListener()
325 {
326
327 public void skippedComparison( Node arg0, Node arg1 )
328 {
329
330 }
331
332 public int differenceFound( Difference difference )
333 {
334 if ( "${remoterepo}".equals( difference.getControlNodeDetail().getValue() ) &&
335 remoteRepositoryURL.equals( difference.getTestNodeDetail().getValue() ) )
336 {
337 return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
338 }
339 else
340 {
341 return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
342 }
343 }
344 });
345 diff.appendMessage( sb );
346
347 XMLAssert.assertXMLIdentical( diff, true );
348 }
349 catch ( SAXException e )
350 {
351 fail( e.getMessage() );
352 }
353 finally
354 {
355 IOUtil.close( expected );
356 IOUtil.close( actual );
357 }
358 }
359
360 private String getRemoteRepositoryURL()
361 throws IOException
362 {
363 File testFile = getTestFile( "src/test/remote-repository" );
364 if (testFile.getAbsolutePath().equals( testFile.getCanonicalPath() ) )
365 {
366 return "file://" + getTestFile( "src/test/remote-repository" ).getAbsolutePath().replace( '\\', '/' );
367 }
368 return "file://" + getTestFile( "src/test/remote-repository" ).getCanonicalPath().replace( '\\', '/' );
369 }
370
371 public static String getPath( File file )
372 throws IOException
373 {
374 return ReleaseUtil.isSymlink( file ) ? file.getCanonicalPath() : file.getAbsolutePath();
375 }
376 }