1 package org.apache.maven.shared.release.util;
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.Arrays;
26 import java.util.List;
27 import java.util.Locale;
28
29 import org.apache.commons.io.FilenameUtils;
30 import org.apache.commons.lang.StringUtils;
31 import org.apache.maven.model.Model;
32 import org.apache.maven.project.MavenProject;
33 import org.apache.maven.shared.release.ReleaseExecutionException;
34 import org.apache.maven.shared.release.config.ReleaseDescriptor;
35 import org.codehaus.plexus.interpolation.InterpolationException;
36 import org.codehaus.plexus.interpolation.MapBasedValueSource;
37 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
38 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
39 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
40 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
41 import org.codehaus.plexus.util.FileUtils;
42 import org.codehaus.plexus.util.IOUtil;
43 import org.codehaus.plexus.util.ReaderFactory;
44
45
46
47
48
49 public class ReleaseUtil
50 {
51 @SuppressWarnings( "checkstyle:constantname" )
52 public static final String RELEASE_POMv4 = "release-pom.xml";
53
54 @SuppressWarnings( "checkstyle:constantname" )
55 public static final String POMv4 = "pom.xml";
56
57 private static final String FS = File.separator;
58
59
60
61
62 public static final String LS = System.getProperty( "line.separator" );
63
64 private ReleaseUtil()
65 {
66
67 }
68
69 public static MavenProject getRootProject( List<MavenProject> reactorProjects )
70 {
71 MavenProject project = reactorProjects.get( 0 );
72 for ( MavenProject currentProject : reactorProjects )
73 {
74 if ( currentProject.isExecutionRoot() )
75 {
76 project = currentProject;
77 break;
78 }
79 }
80
81 return project;
82 }
83
84 public static File getStandardPom( MavenProject project )
85 {
86 if ( project == null )
87 {
88 return null;
89 }
90
91 File pom = project.getFile();
92
93 if ( pom == null )
94 {
95 return null;
96 }
97
98 File releasePom = getReleasePom( project );
99 if ( pom.equals( releasePom ) )
100 {
101 pom = new File( pom.getParent(), POMv4 );
102 }
103
104 return pom;
105 }
106
107 public static File getReleasePom( MavenProject project )
108 {
109 if ( project == null )
110 {
111 return null;
112 }
113
114 File pom = project.getFile();
115
116 if ( pom == null )
117 {
118 return null;
119 }
120
121 return new File( pom.getParent(), RELEASE_POMv4 );
122 }
123
124
125
126
127
128
129
130
131
132
133 public static String readXmlFile( File file )
134 throws IOException
135 {
136 return readXmlFile( file, LS );
137 }
138
139 public static String readXmlFile( File file, String ls )
140 throws IOException
141 {
142 Reader reader = null;
143 try
144 {
145 reader = ReaderFactory.newXmlReader( file );
146 return normalizeLineEndings( IOUtil.toString( reader ), ls );
147 }
148 finally
149 {
150 IOUtil.close( reader );
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163 public static String normalizeLineEndings( String text, String separator )
164 {
165 String norm = text;
166 if ( text != null )
167 {
168 norm = text.replaceAll( "(\r\n)|(\n)|(\r)", separator );
169 }
170 return norm;
171 }
172
173 public static ReleaseDescriptor createBasedirAlignedReleaseDescriptor( ReleaseDescriptor releaseDescriptor,
174 List<MavenProject> reactorProjects )
175 throws ReleaseExecutionException
176 {
177 String basedir;
178 try
179 {
180 basedir = getCommonBasedir( reactorProjects );
181 }
182 catch ( IOException e )
183 {
184 throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
185 + e.getMessage(), e );
186 }
187
188 int parentLevels =
189 getBaseWorkingDirectoryParentCount( basedir,
190 FileUtils.normalize( releaseDescriptor.getWorkingDirectory() ) );
191
192 String url = releaseDescriptor.getScmSourceUrl();
193 url = realignScmUrl( parentLevels, url );
194
195 ReleaseDescriptor descriptor = new ReleaseDescriptor();
196 descriptor.setWorkingDirectory( basedir );
197 descriptor.setScmSourceUrl( url );
198 return descriptor;
199 }
200
201 public static String getCommonBasedir( List<MavenProject> reactorProjects )
202 throws IOException
203 {
204 return getCommonBasedir( reactorProjects, FS );
205 }
206
207 public static String getCommonBasedir( List<MavenProject> reactorProjects, String separator )
208 throws IOException
209 {
210 String[] baseDirs = new String[reactorProjects.size()];
211 int idx = 0;
212 for ( MavenProject p : reactorProjects )
213 {
214 String dir = p.getBasedir().getCanonicalPath();
215
216
217
218 if ( !dir.endsWith( separator ) )
219 {
220 dir = dir + separator;
221 }
222 baseDirs[idx++] = dir;
223 }
224
225 String basedir = StringUtils.getCommonPrefix( baseDirs );
226
227 int separatorPos = basedir.lastIndexOf( separator );
228 if ( !basedir.endsWith( separator ) && separatorPos >= 0 )
229 {
230 basedir = basedir.substring( 0, separatorPos );
231 }
232
233 if ( basedir.endsWith( separator ) && basedir.length() > 1 )
234 {
235 basedir = basedir.substring( 0, basedir.length() - 1 );
236 }
237
238 return basedir;
239 }
240
241 public static int getBaseWorkingDirectoryParentCount( String basedir, String workingDirectory )
242 {
243 int num = 0;
244
245
246
247 workingDirectory = FilenameUtils.normalize( workingDirectory.toLowerCase( Locale.ENGLISH ) );
248 basedir = FilenameUtils.normalize( basedir.toLowerCase( Locale.ENGLISH ) );
249
250
251
252
253 File workingDirectoryFile = new File( workingDirectory, ".tmp" ).getParentFile();
254 File basedirFile = new File( basedir, ".tmp" ).getParentFile();
255
256 if ( !workingDirectoryFile.equals( basedirFile ) && workingDirectory.startsWith( basedir ) )
257 {
258 do
259 {
260 workingDirectoryFile = workingDirectoryFile.getParentFile();
261 num++;
262 }
263 while ( !workingDirectoryFile.equals( basedirFile ) );
264 }
265 return num;
266 }
267
268 public static String realignScmUrl( int parentLevels, String url )
269 {
270 if ( !StringUtils.isEmpty( url ) )
271 {
272
273 url = url.replaceAll( "/\\./", "/" ).replaceAll( "/\\.$", "" ).
274 replaceAll( "/[^/]+/\\.\\./", "/" ).replaceAll( "/[^/]+/\\.\\.$", "" );
275
276 int index = url.length();
277 String suffix = "";
278 if ( url.endsWith( "/" ) )
279 {
280 index--;
281 suffix = "/";
282 }
283
284 for ( int i = 0; i < parentLevels && index > 0; i++ )
285 {
286 index = url.lastIndexOf( '/', index - 1 );
287 }
288
289 if ( index > 0 )
290 {
291 url = url.substring( 0, index ) + suffix;
292 }
293
294 }
295 return url;
296 }
297
298 public static boolean isSymlink( File file )
299 throws IOException
300 {
301 return !file.getAbsolutePath().equals( file.getCanonicalPath() );
302 }
303
304 public static String interpolate( String value, Model model )
305 throws ReleaseExecutionException
306 {
307 if ( value != null && value.contains( "${" ) )
308 {
309 StringSearchInterpolator interpolator = new StringSearchInterpolator();
310 List<String> pomPrefixes = Arrays.asList( "pom.", "project." );
311 interpolator.addValueSource( new PrefixedObjectValueSource( pomPrefixes, model, false ) );
312 interpolator.addValueSource( new MapBasedValueSource( model.getProperties() ) );
313 interpolator.addValueSource( new ObjectBasedValueSource( model ) );
314 try
315 {
316 value = interpolator.interpolate( value, new PrefixAwareRecursionInterceptor( pomPrefixes ) );
317 }
318 catch ( InterpolationException e )
319 {
320 throw new ReleaseExecutionException(
321 "Failed to interpolate " + value + " for project " + model.getId(),
322 e );
323 }
324 }
325 return value;
326 }
327 }