Skip to content

Commit 227abc9

Browse files
committed
Implemented updating of md5 hashes in artifacts.xml, removed timestampPrefix option
1 parent 6469215 commit 227abc9

File tree

6 files changed

+137
-19
lines changed

6 files changed

+137
-19
lines changed

build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ osspub {
5252
namespace 'org.eclipse.xtend'
5353
namespace 'org.eclipse.lsp4j'
5454
referenceFeature 'org.eclipse.xtext.sdk'
55-
timestampPrefix 'v'
5655
}
5756

5857
p2Repository {
@@ -61,6 +60,5 @@ osspub {
6160
url "http://services.typefox.io/open-source/jenkins/job/lsp4j/job/${osspub.branch}/lastStableBuild/artifact/build/lsp4j.p2-repository-${osspub.version}.zip"
6261
namespace 'org.eclipse.lsp4j'
6362
referenceFeature 'org.eclipse.lsp4j.sdk'
64-
timestampPrefix 'v'
6563
}
6664
}

buildSrc/src/main/java/io/typefox/publishing/EclipsePublishing.xtend

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,29 @@
77
*******************************************************************************/
88
package io.typefox.publishing
99

10+
import com.google.common.collect.AbstractIterator
1011
import com.google.common.io.Files
1112
import java.io.File
13+
import java.io.FileOutputStream
1214
import java.io.FilenameFilter
15+
import java.io.IOException
1316
import java.nio.charset.Charset
1417
import java.util.concurrent.Callable
18+
import java.util.jar.JarFile
19+
import java.util.jar.JarOutputStream
20+
import java.util.zip.ZipEntry
21+
import javax.xml.parsers.DocumentBuilderFactory
22+
import javax.xml.transform.TransformerFactory
23+
import javax.xml.transform.dom.DOMSource
24+
import javax.xml.transform.stream.StreamResult
1525
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
26+
import org.gradle.api.GradleException
1627
import org.gradle.api.InvalidUserDataException
1728
import org.gradle.api.Project
1829
import org.gradle.api.tasks.Copy
1930
import org.gradle.api.tasks.Delete
2031
import org.gradle.api.tasks.bundling.Zip
32+
import org.w3c.dom.Element
2133
import pw.prok.download.Download
2234

2335
@FinalFieldsConstructor
@@ -99,6 +111,13 @@ class EclipsePublishing {
99111
] as Callable<File[]>)
100112
outputDir = file('''«rootDir»/build-result/p2.repository/features''')
101113
]
114+
115+
task('''update«repoName»ArtifactsChecksum''') => [
116+
doLast [
117+
updateArtifactsXml('''«buildDir»/p2-«repoName.toLowerCase»/repository-unsigned''',
118+
'''«rootDir»/build-result/p2.repository''')
119+
]
120+
]
102121
}
103122

104123
val copyP2MetadataTask = task(#{'type' -> Copy}, '''copy«repoName»P2Metadata''') => [ task |
@@ -109,6 +128,7 @@ class EclipsePublishing {
109128
from = '''«buildDir»/p2-«repoName.toLowerCase»/repository-unsigned'''
110129
into = '''«rootDir»/build-result/p2.repository'''
111130
if (osspub.signJars) {
131+
exclude('**/artifacts.jar')
112132
for (namespace : repository.namespaces) {
113133
exclude('''**/«namespace»*.jar''')
114134
}
@@ -121,7 +141,7 @@ class EclipsePublishing {
121141
description = '''Create a zip file from the «repoName» P2 repository'''
122142
dependsOn(copyP2MetadataTask)
123143
if (osspub.signJars)
124-
dependsOn('''sign«repoName»P2Plugins''', '''sign«repoName»P2Features''')
144+
dependsOn('''sign«repoName»P2Plugins''', '''sign«repoName»P2Features''', '''update«repoName»ArtifactsChecksum''')
125145
from = '''«rootDir»/build-result/p2.repository'''
126146
destinationDir = file('''«rootDir»/build-result/downloads''')
127147
doFirst[ task2 |
@@ -189,15 +209,22 @@ class EclipsePublishing {
189209

190210
private def getBuildTimestamp(P2Repository repository) {
191211
if (!repository.referenceFeature.nullOrEmpty) {
192-
val referencePrefix = '''«repository.referenceFeature»_«mainVersion».«repository.timestampPrefix»'''
212+
val referencePrefix = '''«repository.referenceFeature»_«mainVersion».'''
193213
val bundleDir = new File(buildDir, '''p2-«repository.name.toLowerCase»/repository-unsigned/features''')
194214
val FilenameFilter filter = [ dir, name |
195215
name.startsWith(referencePrefix) && name.endsWith('.jar')
196216
]
197217
val referenceFeatureFiles = bundleDir.listFiles(filter)
198218
if (referenceFeatureFiles.length > 0) {
199219
val fileName = referenceFeatureFiles.get(0).name
200-
return fileName.substring(referencePrefix.length, fileName.length - '.jar'.length).replace('-', '')
220+
val qualifier = fileName.substring(referencePrefix.length, fileName.length - '.jar'.length)
221+
val timestamp = new StringBuilder
222+
for (var i = 0; i < qualifier.length; i++) {
223+
val c = qualifier.charAt(i)
224+
if (Character.isDigit(c))
225+
timestamp.append(c)
226+
}
227+
return timestamp.toString
201228
}
202229
}
203230
}
@@ -210,4 +237,72 @@ class EclipsePublishing {
210237
}
211238
}
212239

240+
private def updateArtifactsXml(String sourceDir, String destDir) {
241+
var JarFile sourceJar
242+
var JarOutputStream targetJar
243+
try {
244+
sourceJar = new JarFile('''«sourceDir»/artifacts.jar''')
245+
val artifactsEntry = sourceJar.getEntry('artifacts.xml')
246+
if (artifactsEntry === null)
247+
throw new GradleException('artifacts.jar does not contain artifacts.xml')
248+
val builder = DocumentBuilderFactory.newInstance.newDocumentBuilder
249+
val document = builder.parse(sourceJar.getInputStream(artifactsEntry))
250+
val xmlRoot = document.documentElement
251+
if (xmlRoot.tagName == 'repository') {
252+
for (artifacts : xmlRoot.getElements('artifacts')) {
253+
for (artifact : artifacts.getElements('artifact')) {
254+
for (properties : artifact.getElements('properties')) {
255+
for (property : properties.getElements('property')) {
256+
if (property.getAttribute('name') == 'download.md5') {
257+
val id = artifact.getAttribute('id')
258+
val version = artifact.getAttribute('version')
259+
val classifier = artifact.getAttribute('classifier')
260+
if (!id.empty && !version.empty && !classifier.empty) {
261+
val md5 = computeMd5Checksum(sourceDir, id, version, classifier)
262+
property.setAttribute('value', md5)
263+
}
264+
}
265+
}
266+
}
267+
}
268+
}
269+
}
270+
271+
targetJar = new JarOutputStream(new FileOutputStream('''«destDir»/artifacts.jar'''))
272+
targetJar.putNextEntry(new ZipEntry('artifacts.xml'))
273+
val transformer = TransformerFactory.newInstance.newTransformer
274+
transformer.transform(new DOMSource(document), new StreamResult(targetJar))
275+
targetJar.closeEntry()
276+
} finally {
277+
try {
278+
sourceJar?.close()
279+
targetJar?.close()
280+
} catch (IOException e) {}
281+
}
282+
}
283+
284+
private def Iterable<Element> getElements(Element e, String name) {
285+
val nodeList = e.getElementsByTagName(name)
286+
return [
287+
new AbstractIterator<Element> {
288+
int i = 0
289+
override protected computeNext() {
290+
if (i < nodeList.length)
291+
return nodeList.item(i++) as Element
292+
else
293+
return endOfData
294+
}
295+
}
296+
]
297+
}
298+
299+
private def computeMd5Checksum(String sourceDir, String id, String version, String classifier) {
300+
val sourcePath = switch classifier {
301+
case 'osgi.bundle': '''«sourceDir»/plugins/«id»_«version».jar'''
302+
case 'org.eclipse.update.feature': '''«sourceDir»/features/«id»_«version».jar'''
303+
}
304+
val bytes = FileChecksums.getMd5Checksum(new File(sourcePath))
305+
return FileChecksums.toString(bytes)
306+
}
307+
213308
}

buildSrc/src/main/java/io/typefox/publishing/FileChecksums.xtend

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import java.io.FileInputStream
1212
import java.io.FileNotFoundException
1313
import java.io.IOException
1414
import java.io.InputStream
15+
import java.security.DigestInputStream
16+
import java.security.MessageDigest
1517
import java.util.zip.CRC32
1618

1719
class FileChecksums {
1820

19-
static def long getChecksum(File file) throws FileNotFoundException, IOException {
21+
static def long getCrcChecksum(File file) throws FileNotFoundException, IOException {
2022
val checksum = new CRC32
2123
var InputStream inputStream
2224
try {
@@ -35,4 +37,33 @@ class FileChecksums {
3537
}
3638
}
3739

40+
static def byte[] getMd5Checksum(File file) throws FileNotFoundException, IOException {
41+
val messageDigest = MessageDigest.getInstance('MD5')
42+
var DigestInputStream digestInputStream
43+
try {
44+
digestInputStream = new DigestInputStream(new FileInputStream(file), messageDigest)
45+
val buffer = newByteArrayOfSize(4096)
46+
var int bytesRead
47+
do {
48+
bytesRead = digestInputStream.read(buffer)
49+
} while (bytesRead > 0)
50+
} finally {
51+
try {
52+
digestInputStream?.close()
53+
} catch (IOException e) {}
54+
}
55+
return messageDigest.digest()
56+
}
57+
58+
static def String toString(byte[] bytes) {
59+
val result = new StringBuilder
60+
for (var i = 0; i < bytes.length; i++) {
61+
var value = bytes.get(i) as int
62+
if (value < 0)
63+
value += 0x100
64+
result.append(Integer.toString(value, 16))
65+
}
66+
return result.toString
67+
}
68+
3869
}

buildSrc/src/main/java/io/typefox/publishing/JarSignTask.xtend

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ class JarSignTask extends DefaultTask {
6161
val sourceIdentifier = source.name.identifier
6262
val FilenameFilter filter = [dir, name | name.identifier == sourceIdentifier]
6363
val matching = alternateSourceDir.listFiles(filter)
64-
if (matching.length > 0) {
65-
val sourceChecksum = source.checksum
66-
val equalSourceFile = matching.findFirst[checksum == sourceChecksum]
64+
if (matching !== null && matching.length > 0) {
65+
val sourceChecksum = source.crcChecksum
66+
val equalSourceFile = matching.findFirst[crcChecksum == sourceChecksum]
6767
if (equalSourceFile === null) {
6868
val message = '''The artifact «source.withoutRootPath» matches «matching.map[withoutRootPath].join(', ')», but their content is unequal.'''
6969
if (failOnInconsistency)

buildSrc/src/main/java/io/typefox/publishing/MavenPublishing.xtend

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import org.apache.maven.settings.building.DefaultSettingsBuilderFactory
1212
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest
1313
import org.apache.maven.settings.building.SettingsBuildingException
1414
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
15-
import org.gradle.api.GradleScriptException
15+
import org.gradle.api.GradleException
1616
import org.gradle.api.InvalidUserDataException
1717
import org.gradle.api.Project
1818
import org.gradle.api.artifacts.ConfigurablePublishArtifact
@@ -265,7 +265,7 @@ class MavenPublishing {
265265
username = server.username
266266
if (cipher.isEncryptedString(server.password)) {
267267
if (decryptionKey === null)
268-
throw new GradleScriptException('Missing settings-security.xml file.', null)
268+
throw new GradleException('Missing settings-security.xml file.')
269269
logger.info('''Maven Settings: using encrypted server entry for «repository.name» repository''')
270270
password = cipher.decryptDecorated(server.password, decryptionKey)
271271
} else {
@@ -281,7 +281,7 @@ class MavenPublishing {
281281
if (gpgServer !== null) {
282282
if (cipher.isEncryptedString(gpgServer.passphrase)) {
283283
if (decryptionKey === null)
284-
throw new GradleScriptException('Missing settings-security.xml file.', null)
284+
throw new GradleException('Missing settings-security.xml file.')
285285
logger.info('Maven Settings: using encrypted server entry for pgp signing')
286286
ext.set(PublishingPlugin.SIGNING_PASSWORD, cipher.decryptDecorated(gpgServer.passphrase, decryptionKey))
287287
} else {
@@ -290,7 +290,7 @@ class MavenPublishing {
290290
}
291291
}
292292
} catch (SettingsBuildingException e) {
293-
throw new GradleScriptException('Error while loading Maven settings.', e)
293+
throw new GradleException('Error while loading Maven settings.', e)
294294
}
295295
}
296296

buildSrc/src/main/java/io/typefox/publishing/P2Repository.xtend

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ class P2Repository {
2323

2424
String referenceFeature
2525

26-
String timestampPrefix
27-
2826
def void name(Object input) {
2927
this.name = input.toString
3028
}
@@ -45,8 +43,4 @@ class P2Repository {
4543
this.referenceFeature = input.toString
4644
}
4745

48-
def void timestampPrefix(Object input) {
49-
this.timestampPrefix = input.toString
50-
}
51-
5246
}

0 commit comments

Comments
 (0)