1 package org.apache.maven.wrapper;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedOutputStream;
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.io.OutputStream;
30 import java.net.URI;
31 import java.util.ArrayList;
32 import java.util.Enumeration;
33 import java.util.Formatter;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.zip.ZipEntry;
37 import java.util.zip.ZipFile;
38
39
40
41
42
43
44
45 public class Installer
46 {
47 public static final String DEFAULT_DISTRIBUTION_PATH = "wrapper/dists";
48
49 private final Downloader download;
50
51 private final PathAssembler pathAssembler;
52
53 public Installer( Downloader download, PathAssembler pathAssembler )
54 {
55 this.download = download;
56 this.pathAssembler = pathAssembler;
57 }
58
59 public File createDist( WrapperConfiguration configuration )
60 throws Exception
61 {
62 URI distributionUrl = configuration.getDistribution();
63
64 String mvnwRepoUrl = System.getenv( MavenWrapperMain.MVNW_REPOURL );
65 if ( mvnwRepoUrl != null && !mvnwRepoUrl.isEmpty() )
66 {
67 Logger.info( "Detected MVNW_REPOURL environment variable " + mvnwRepoUrl );
68 String mvnPath = distributionUrl.toURL().toString();
69 mvnPath = mvnPath.substring( mvnPath.indexOf( "org/apache/maven" ) );
70 distributionUrl = new URI( mvnwRepoUrl + "/" + mvnPath );
71 }
72
73 boolean alwaysDownload = configuration.isAlwaysDownload();
74 boolean alwaysUnpack = configuration.isAlwaysUnpack();
75
76 PathAssembler.LocalDistribution localDistribution = pathAssembler.getDistribution( configuration );
77 Logger.info( "Installing Maven distribution " + localDistribution.getDistributionDir().getAbsolutePath() );
78
79 File localZipFile = localDistribution.getZipFile();
80 boolean downloaded = false;
81 if ( alwaysDownload || !localZipFile.exists() )
82 {
83 File tmpZipFile = new File( localZipFile.getParentFile(), localZipFile.getName() + ".part" );
84 tmpZipFile.delete();
85 Logger.info( "Downloading " + distributionUrl );
86 download.download( distributionUrl, tmpZipFile );
87 tmpZipFile.renameTo( localZipFile );
88 downloaded = true;
89 }
90
91 File distDir = localDistribution.getDistributionDir();
92 List<File> dirs = listDirs( distDir );
93
94 if ( downloaded || alwaysUnpack || dirs.isEmpty() )
95 {
96 for ( File dir : dirs )
97 {
98 Logger.info( "Deleting directory " + dir.getAbsolutePath() );
99 deleteDir( dir );
100 }
101 Logger.info( "Unzipping " + localZipFile.getAbsolutePath() + " to " + distDir.getAbsolutePath() );
102 unzip( localZipFile, distDir );
103 dirs = listDirs( distDir );
104 if ( dirs.isEmpty() )
105 {
106 throw new RuntimeException( String.format( "Maven distribution '%s' does not contain any directory."
107 + " Expected to find exactly 1 directory.", distDir ) );
108 }
109 setExecutablePermissions( dirs.get( 0 ) );
110 }
111 if ( dirs.size() != 1 )
112 {
113 throw new RuntimeException( String.format( "Maven distribution '%s' contains too many directories."
114 + " Expected to find exactly 1 directory.", distDir ) );
115 }
116 return dirs.get( 0 );
117 }
118
119 private List<File> listDirs( File distDir )
120 {
121 List<File> dirs = new ArrayList<File>();
122 if ( distDir.exists() )
123 {
124 for ( File file : distDir.listFiles() )
125 {
126 if ( file.isDirectory() )
127 {
128 dirs.add( file );
129 }
130 }
131 }
132 return dirs;
133 }
134
135 private void setExecutablePermissions( File mavenHome )
136 {
137 if ( isWindows() )
138 {
139 return;
140 }
141 File mavenCommand = new File( mavenHome, "bin/mvn" );
142 String errorMessage = null;
143 try
144 {
145 ProcessBuilder pb = new ProcessBuilder( "chmod", "755", mavenCommand.getCanonicalPath() );
146 Process p = pb.start();
147 if ( p.waitFor() == 0 )
148 {
149 Logger.info( "Set executable permissions for: " + mavenCommand.getAbsolutePath() );
150 }
151 else
152 {
153 try ( BufferedReader is = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
154 Formatter stdout = new Formatter() )
155 {
156 String line;
157 while ( ( line = is.readLine() ) != null )
158 {
159 stdout.format( "%s%n", line );
160 }
161 errorMessage = stdout.toString();
162 }
163 }
164 }
165 catch ( IOException | InterruptedException e )
166 {
167 errorMessage = e.getMessage();
168 }
169 if ( errorMessage != null )
170 {
171 Logger.warn( "Could not set executable permissions for: " + mavenCommand.getAbsolutePath() );
172 Logger.warn( "Please do this manually if you want to use Maven." );
173 }
174 }
175
176 private boolean isWindows()
177 {
178 String osName = System.getProperty( "os.name" ).toLowerCase( Locale.US );
179 if ( osName.indexOf( "windows" ) > -1 )
180 {
181 return true;
182 }
183 return false;
184 }
185
186 private boolean deleteDir( File dir )
187 {
188 if ( dir.isDirectory() )
189 {
190 String[] children = dir.list();
191 for ( int i = 0; i < children.length; i++ )
192 {
193 boolean success = deleteDir( new File( dir, children[i] ) );
194 if ( !success )
195 {
196 return false;
197 }
198 }
199 }
200
201
202 return dir.delete();
203 }
204
205 public void unzip( File zip, File dest )
206 throws IOException
207 {
208 Enumeration entries;
209 ZipFile zipFile = new ZipFile( zip );
210
211 entries = zipFile.entries();
212
213 while ( entries.hasMoreElements() )
214 {
215 ZipEntry entry = (ZipEntry) entries.nextElement();
216
217 if ( entry.isDirectory() )
218 {
219 ( new File( dest, entry.getName() ) ).mkdirs();
220 continue;
221 }
222
223 new File( dest, entry.getName() ).getParentFile().mkdirs();
224
225 try ( InputStream in = zipFile.getInputStream( entry );
226 OutputStream out =
227 new BufferedOutputStream( new FileOutputStream( new File( dest, entry.getName() ) ) ) )
228 {
229 byte[] buffer = new byte[1024];
230 int len;
231
232 while ( ( len = in.read( buffer ) ) >= 0 )
233 {
234 out.write( buffer, 0, len );
235 }
236 }
237 }
238 zipFile.close();
239 }
240 }