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