1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.argeo.slc.repo.maven;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Set;
21 import java.util.StringTokenizer;
22 import java.util.TreeSet;
23
24 import javax.jcr.Credentials;
25 import javax.jcr.Node;
26 import javax.jcr.NodeIterator;
27 import javax.jcr.Repository;
28 import javax.jcr.RepositoryException;
29 import javax.jcr.Session;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.argeo.jcr.JcrMonitor;
34 import org.argeo.jcr.JcrUtils;
35 import org.argeo.slc.SlcException;
36 import org.argeo.slc.SlcNames;
37 import org.argeo.slc.SlcTypes;
38 import org.argeo.slc.repo.ArtifactIndexer;
39 import org.argeo.slc.repo.RepoConstants;
40 import org.argeo.slc.repo.RepoUtils;
41 import org.eclipse.aether.artifact.Artifact;
42 import org.eclipse.aether.artifact.DefaultArtifact;
43 import org.osgi.framework.Version;
44
45
46
47
48
49 public class GenerateBinaries implements Runnable, SlcNames {
50 private final static Log log = LogFactory.getLog(GenerateBinaries.class);
51
52
53 private Repository repository;
54 private Credentials credentials;
55 private String workspace;
56
57
58 private String groupId;
59 private String parentPomCoordinates;
60 private String version = null;
61
62
63 private String artifactBasePath = RepoConstants.DEFAULT_ARTIFACTS_BASE_PATH;
64 private List<String> excludedSuffixes = new ArrayList<String>();
65
66
67 private Set<Artifact> binaries = new TreeSet<Artifact>(
68 new ArtifactIdComparator());
69 private Set<Artifact> sources = new TreeSet<Artifact>(
70 new ArtifactIdComparator());
71
72
73 private ArtifactIndexer artifactIndexer = new ArtifactIndexer();
74 private Node allArtifactsHighestVersion;
75
76 public void run() {
77 Session session = null;
78 try {
79 session = repository.login(credentials, workspace);
80 Node groupNode = session.getNode(MavenConventionsUtils.groupPath(
81 artifactBasePath, groupId));
82 internalPreProcessing(groupNode, null);
83 internalProcessing(groupNode, null);
84 } catch (Exception e) {
85 throw new SlcException("Cannot normalize group " + groupId + " in "
86 + workspace, e);
87 } finally {
88 JcrUtils.logoutQuietly(session);
89 }
90 }
91
92
93
94
95
96
97
98
99
100
101
102 public static void processGroupNode(Node groupNode, String version,
103 JcrMonitor monitor) throws RepositoryException {
104
105 GenerateBinaries gb = new GenerateBinaries();
106 String groupId = groupNode.getProperty(SlcNames.SLC_GROUP_BASE_ID)
107 .getString();
108 gb.setGroupId(groupId);
109 gb.setVersion(version);
110
111 gb.internalPreProcessing(groupNode, monitor);
112 gb.internalProcessing(groupNode, monitor);
113 }
114
115
116 public static GenerateBinaries preProcessGroupNode(Node groupNode,
117 JcrMonitor monitor) throws RepositoryException {
118
119 GenerateBinaries gb = new GenerateBinaries();
120 String groupId = groupNode.getProperty(SlcNames.SLC_GROUP_BASE_ID)
121 .getString();
122 gb.setGroupId(groupId);
123
124
125 gb.internalPreProcessing(groupNode, monitor);
126 return gb;
127 }
128
129
130 public Set<Artifact> getBinaries() {
131 return binaries;
132 }
133
134 public Artifact getHighestArtifactVersion() throws RepositoryException {
135 return allArtifactsHighestVersion == null ? null : RepoUtils
136 .asArtifact(allArtifactsHighestVersion);
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150 protected void internalPreProcessing(Node groupNode, JcrMonitor monitor)
151 throws RepositoryException {
152 if (monitor != null)
153 monitor.subTask("Pre processing group " + groupId);
154
155
156
157 allArtifactsHighestVersion = null;
158
159 aBases: for (NodeIterator aBases = groupNode.getNodes(); aBases
160 .hasNext();) {
161 Node aBase = aBases.nextNode();
162 if (aBase.isNodeType(SlcTypes.SLC_ARTIFACT_BASE)) {
163 Node highestAVersion = getArtifactLatestVersion(aBase);
164 if (highestAVersion == null)
165 continue aBases;
166 else {
167
168
169 for (NodeIterator files = highestAVersion.getNodes(); files
170 .hasNext();) {
171 Node file = files.nextNode();
172 if (file.isNodeType(SlcTypes.SLC_BUNDLE_ARTIFACT)) {
173 if (log.isDebugEnabled())
174 log.debug("Pre-Processing " + file.getName());
175 preProcessBundleArtifact(file);
176 }
177 }
178 }
179 }
180 }
181
182
183
184
185
186 }
187
188
189 protected void internalProcessing(Node groupNode, JcrMonitor monitor)
190 throws RepositoryException {
191 if (monitor != null)
192 monitor.subTask("Processing group " + groupId);
193
194 Session session = groupNode.getSession();
195
196
197
198
199
200 if (version == null || version.trim().equals(""))
201 if (allArtifactsHighestVersion != null)
202 version = allArtifactsHighestVersion.getProperty(
203 SLC_ARTIFACT_VERSION).getString();
204 else
205 throw new SlcException("Group version " + version
206 + " is empty.");
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 Set<Artifact> indexes = new TreeSet<Artifact>(
222 new ArtifactIdComparator());
223
224 Artifact indexArtifact;
225 indexArtifact = writeIndex(session, RepoConstants.BINARIES_ARTIFACT_ID,
226 binaries);
227 indexes.add(indexArtifact);
228
229 indexArtifact = writeIndex(session, RepoConstants.SOURCES_ARTIFACT_ID,
230 sources);
231 indexes.add(indexArtifact);
232
233
234 writeIndex(session, RepoConstants.SDK_ARTIFACT_ID, indexes);
235
236 if (monitor != null)
237 monitor.worked(1);
238 }
239
240 protected void preProcessBundleArtifact(Node bundleNode)
241 throws RepositoryException {
242
243 String symbolicName = JcrUtils.get(bundleNode, SLC_SYMBOLIC_NAME);
244
245 if (symbolicName == null)
246 log.warn("Symbolic name is null for bundle " + bundleNode);
247
248
249 if (symbolicName.endsWith(".source")) {
250
251 String bundleName = RepoUtils
252 .extractBundleNameFromSourceName(symbolicName);
253 for (String excludedSuffix : excludedSuffixes) {
254 if (bundleName.endsWith(excludedSuffix))
255 return;
256 }
257 sources.add(RepoUtils.asArtifact(bundleNode));
258 return;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 binaries.add(RepoUtils.asArtifact(bundleNode));
277
278
279 if (bundleNode.getSession().hasPendingChanges())
280 throw new SlcException("Pending changes in the session, "
281 + "this should not be true here.");
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 private Artifact writeIndex(Session session, String artifactId,
311 Set<Artifact> artifacts) throws RepositoryException {
312 Artifact artifact = new DefaultArtifact(groupId, artifactId, "pom",
313 version);
314 Artifact parentArtifact = parentPomCoordinates != null ? new DefaultArtifact(
315 parentPomCoordinates) : null;
316 String pom = MavenConventionsUtils.artifactsAsDependencyPom(artifact,
317 artifacts, parentArtifact);
318 Node node = RepoUtils.copyBytesAsArtifact(
319 session.getNode(artifactBasePath), artifact, pom.getBytes());
320 artifactIndexer.index(node);
321
322
323 String pomSha = JcrUtils.checksumFile(node, "SHA-1");
324 JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".sha1",
325 pomSha.getBytes());
326 String pomMd5 = JcrUtils.checksumFile(node, "MD5");
327 JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".md5",
328 pomMd5.getBytes());
329 session.save();
330 return artifact;
331 }
332
333
334 private Node getArtifactLatestVersion(Node artifactBase) {
335 try {
336 Node highestAVersion = null;
337 for (NodeIterator aVersions = artifactBase.getNodes(); aVersions
338 .hasNext();) {
339 Node aVersion = aVersions.nextNode();
340 if (aVersion.isNodeType(SlcTypes.SLC_ARTIFACT_VERSION_BASE)) {
341 if (highestAVersion == null) {
342 highestAVersion = aVersion;
343 if (allArtifactsHighestVersion == null)
344 allArtifactsHighestVersion = aVersion;
345
346
347 else {
348 Version cachedHighestVersion = extractOsgiVersion(allArtifactsHighestVersion);
349 Version currVersion = extractOsgiVersion(aVersion);
350 if (currVersion.compareTo(cachedHighestVersion) > 0)
351 allArtifactsHighestVersion = aVersion;
352 }
353 } else {
354 Version currVersion = extractOsgiVersion(aVersion);
355 Version currentHighestVersion = extractOsgiVersion(highestAVersion);
356 if (currVersion.compareTo(currentHighestVersion) > 0) {
357 highestAVersion = aVersion;
358 }
359 if (currVersion
360 .compareTo(extractOsgiVersion(allArtifactsHighestVersion)) > 0) {
361 allArtifactsHighestVersion = aVersion;
362 }
363 }
364
365 }
366 }
367 return highestAVersion;
368 } catch (RepositoryException re) {
369 throw new SlcException("Unable to get latest version for node "
370 + artifactBase, re);
371 }
372 }
373
374 private Version extractOsgiVersion(Node artifactVersion)
375 throws RepositoryException {
376 String rawVersion = artifactVersion.getProperty(SLC_ARTIFACT_VERSION)
377 .getString();
378 String cleanVersion = rawVersion.replace("-SNAPSHOT", ".SNAPSHOT");
379 Version osgiVersion = null;
380
381 try {
382 osgiVersion = new Version(cleanVersion);
383 } catch (IllegalArgumentException e) {
384 log.error("Version string " + cleanVersion + " is invalid ");
385 String twickedVersion = twickInvalidVersion(cleanVersion);
386 osgiVersion = new Version(twickedVersion);
387 log.error("Using " + twickedVersion + " instead");
388
389 }
390 return osgiVersion;
391 }
392
393 private String twickInvalidVersion(String tmpVersion) {
394 String[] tokens = tmpVersion.split("\\.");
395 if (tokens.length == 3 && tokens[2].lastIndexOf("-") > 0) {
396 String newSuffix = tokens[2].replaceFirst("-", ".");
397 tmpVersion = tmpVersion.replaceFirst(tokens[2], newSuffix);
398 } else if (tokens.length > 4) {
399
400 StringTokenizer st = new StringTokenizer(tmpVersion, ".", true);
401 StringBuilder builder = new StringBuilder();
402
403 builder.append(st.nextToken()).append(st.nextToken());
404
405 builder.append(st.nextToken()).append(st.nextToken());
406
407 builder.append(st.nextToken()).append(st.nextToken());
408
409 builder.append(st.nextToken());
410 while (st.hasMoreTokens()) {
411
412 st.nextToken();
413 if (st.hasMoreTokens())
414 builder.append("-").append(st.nextToken());
415 }
416 tmpVersion = builder.toString();
417 }
418 return tmpVersion;
419 }
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548 public void setRepository(Repository repository) {
549 this.repository = repository;
550 }
551
552 public void setCredentials(Credentials credentials) {
553 this.credentials = credentials;
554 }
555
556 public void setWorkspace(String workspace) {
557 this.workspace = workspace;
558 }
559
560 public void setGroupId(String groupId) {
561 this.groupId = groupId;
562 }
563
564 public void setParentPomCoordinates(String parentPomCoordinates) {
565 this.parentPomCoordinates = parentPomCoordinates;
566 }
567
568 public void setArtifactBasePath(String artifactBasePath) {
569 this.artifactBasePath = artifactBasePath;
570 }
571
572 public void setVersion(String version) {
573 this.version = version;
574 }
575
576 public void setExcludedSuffixes(List<String> excludedSuffixes) {
577 this.excludedSuffixes = excludedSuffixes;
578 }
579
580 public void setArtifactIndexer(ArtifactIndexer artifactIndexer) {
581 this.artifactIndexer = artifactIndexer;
582 }
583 }