1 package org.codehaus.mojo.wagon.shared;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileReader;
21 import java.io.FileWriter;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.Reader;
25 import java.io.Writer;
26 import java.security.MessageDigest;
27 import java.security.NoSuchAlgorithmException;
28
29 import org.apache.maven.artifact.repository.metadata.Metadata;
30 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
31 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
32 import org.apache.maven.plugin.logging.Log;
33 import org.apache.maven.shared.model.fileset.FileSet;
34 import org.apache.maven.wagon.ResourceDoesNotExistException;
35 import org.apache.maven.wagon.Wagon;
36 import org.apache.maven.wagon.WagonException;
37 import org.codehaus.plexus.util.DirectoryScanner;
38 import org.codehaus.plexus.util.FileUtils;
39 import org.codehaus.plexus.util.IOUtil;
40 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
41
42
43
44
45
46
47
48 public class DefaultMavenRepoMerger
49 implements MavenRepoMerger
50 {
51
52
53
54 private WagonDownload downloader;
55
56
57
58
59 private WagonUpload uploader;
60
61 public void merge( Wagon src, Wagon target, boolean optimize, Log logger )
62 throws WagonException, IOException
63 {
64
65
66 File downloadSrcDir = createTempDirectory( "wagon-maven-plugin" );
67
68 WagonFileSet srcFileSet = new WagonFileSet();
69 srcFileSet.setDownloadDirectory( downloadSrcDir );
70
71 String[] excludes = { ".index/**", ".indexer/**, .meta/**, .nexus/**" };
72 srcFileSet.setExcludes( excludes );
73
74 try
75 {
76 downloader.download( src, srcFileSet, logger );
77
78
79 DirectoryScanner scanner = new DirectoryScanner();
80 scanner.setBasedir( downloadSrcDir );
81 String[] includes = { "**/" + MAVEN_METADATA };
82 scanner.setIncludes( includes );
83 scanner.scan();
84 String[] files = scanner.getIncludedFiles();
85
86 for ( int i = 0; i < files.length; ++i )
87 {
88 File srcMetadaFile = new File( downloadSrcDir, files[i] + IN_PROCESS_MARKER );
89
90 try
91 {
92 target.get( files[i].replace( '\\', '/' ), srcMetadaFile );
93 }
94 catch ( ResourceDoesNotExistException e )
95 {
96
97
98 continue;
99 }
100
101 try
102 {
103 mergeMetadata( srcMetadaFile, logger );
104 }
105 catch ( XmlPullParserException e )
106 {
107 throw new IOException( "Metadata file is corrupt " + files[i] + " Reason: " + e.getMessage() );
108 }
109
110 }
111
112
113 FileSet tobeUploadedFileSet = new FileSet();
114 tobeUploadedFileSet.setDirectory( downloadSrcDir.getAbsolutePath() );
115
116 this.uploader.upload( target, tobeUploadedFileSet, optimize, logger );
117
118 }
119 finally
120 {
121 FileUtils.deleteDirectory( downloadSrcDir );
122 }
123
124 }
125
126 private void mergeMetadata( File existingMetadata, Log logger )
127 throws IOException, XmlPullParserException
128 {
129
130 Writer stagedMetadataWriter = null;
131 Reader existingMetadataReader = null;
132 Reader stagedMetadataReader = null;
133 File stagedMetadataFile = null;
134
135 try
136 {
137 MetadataXpp3Reader xppReader = new MetadataXpp3Reader();
138 MetadataXpp3Writer xppWriter = new MetadataXpp3Writer();
139
140
141 existingMetadataReader = new FileReader( existingMetadata );
142 Metadata existing = xppReader.read( existingMetadataReader );
143
144
145 stagedMetadataFile = new File( existingMetadata.getParentFile(), MAVEN_METADATA );
146 stagedMetadataReader = new FileReader( stagedMetadataFile );
147 Metadata staged = xppReader.read( stagedMetadataReader );
148
149
150 existing.merge( staged );
151
152 stagedMetadataWriter = new FileWriter( stagedMetadataFile );
153 xppWriter.write( stagedMetadataWriter, existing );
154
155 logger.info( "Merging metadata file: " + stagedMetadataFile );
156
157 }
158 finally
159 {
160 IOUtil.close( stagedMetadataWriter );
161 IOUtil.close( stagedMetadataReader );
162 IOUtil.close( existingMetadataReader );
163
164 existingMetadata.delete();
165 }
166
167
168
169
170 try
171 {
172 File newMd5 = new File( stagedMetadataFile.getParentFile(), MAVEN_METADATA + ".md5" );
173 FileUtils.fileWrite( newMd5.getAbsolutePath(), checksum( stagedMetadataFile, MD5 ) );
174
175 File newSha1 = new File( stagedMetadataFile.getParentFile(), MAVEN_METADATA + ".sha1" );
176 FileUtils.fileWrite( newSha1.getAbsolutePath(), checksum( stagedMetadataFile, SHA1 ) );
177 }
178 catch ( NoSuchAlgorithmException e )
179 {
180 throw new RuntimeException( e );
181 }
182
183
184
185 }
186
187 private String checksum( File file, String type )
188 throws IOException, NoSuchAlgorithmException
189 {
190 MessageDigest md5 = MessageDigest.getInstance( type );
191
192 InputStream is = new FileInputStream( file );
193
194 byte[] buf = new byte[8192];
195
196 int i;
197
198 while ( ( i = is.read( buf ) ) > 0 )
199 {
200 md5.update( buf, 0, i );
201 }
202
203 IOUtil.close( is );
204
205 return encode( md5.digest() );
206 }
207
208 private String encode( byte[] binaryData )
209 {
210 if ( binaryData.length != 16 && binaryData.length != 20 )
211 {
212 int bitLength = binaryData.length * 8;
213 throw new IllegalArgumentException( "Unrecognised length for binary data: " + bitLength + " bits" );
214 }
215
216 String retValue = "";
217
218 for ( int i = 0; i < binaryData.length; i++ )
219 {
220 String t = Integer.toHexString( binaryData[i] & 0xff );
221
222 if ( t.length() == 1 )
223 {
224 retValue += ( "0" + t );
225 }
226 else
227 {
228 retValue += t;
229 }
230 }
231
232 return retValue.trim();
233 }
234
235 public static File createTempDirectory(String prefix)
236 throws IOException
237 {
238 final File temp;
239
240 temp = File.createTempFile( prefix, Long.toString( System.nanoTime() ) );
241
242 if ( !( temp.delete() ) )
243 {
244 throw new IOException( "Could not delete temp file: " + temp.getAbsolutePath() );
245 }
246
247 if ( !( temp.mkdir() ) )
248 {
249 throw new IOException( "Could not create temp directory: " + temp.getAbsolutePath() );
250 }
251
252 return ( temp );
253 }
254
255 }