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 }